My plotting setup for gnuplot

Why I chose gnuplot

With so many options for plotting - Python libraries such as matplotlib and seaborn; R; Julia; and the must-not-be-named bloatware point-and-click programs, why did I choose gnuplot, a seemingly old-timer plotting program? My answer is simple - gnuplot adheres to the DOTADIW principle - do one thing, and do it well. Gnuplot also gets yearly updates and continues to have reasonable community support.

Templates for gnuplot

Because I have to present results constantly in slide format, I made several templates that I use to generate different sized figures for presentation slides. I have four sizes - a figure that takes up an entire slide, and figures for ÷2, ÷4, ÷8 slide sizes. The templates help me keep text readable and consistent, regardless of the size of the figures I have in a presentation. I also use the templates to regenerate figures from papers I read, to have a homogenous figure style througout a presentation (I use engauge to extract data from research figures).

For fonts, I chose STIX Two and STIX Two Math, because the font’s focus on scientific and engineering publishing.

I decided on the the Okabe-Ito color-palette, due to the palette’s accessibility for color-blind people. I also like the colors.

The setup relies on multiple template files connected through macros. The top-level file is ~/.gnuplot, defining all the different macros.

# ~/.gnuplot
# Main gnuplot startup file.
# It loads shared definitions once and defines aliases for the output profiles.

set macros

# Location of the split configuration files.
# Override this before loading ~/.gnuplot if you keep the files somewhere else.
if (!exists("GP_CONFIG_DIR")) GP_CONFIG_DIR = system("printf %s \"$HOME/.config/gnuplot\"")

load GP_CONFIG_DIR . "/common.gp"

# -----------------------------------------------------------------------------
# Profile aliases
# -----------------------------------------------------------------------------
# Usage examples:
#   @TYPST
#   set output "figure.svg"
#   plot "data.csv" u 1:2 w lp ls 1 title "data"
#
#   @PAPER
#   set output "figure.eps"
#   plot ...
#
#   @PPT
#   set output "figure.png"
#   plot ...

TYPST = "load '" . GP_CONFIG_DIR . "/typst.gp'"
PAPER_PDF = "load '" . GP_CONFIG_DIR . "/paper_pdf.gp'"

# PowerPoint profiles: default is half-slide. Quarter and full-HD variants are
# implemented through PPT_FIGSIZE and the same presentation profile file.
PPT = "PPT_FIGSIZE='half'; load '" . GP_CONFIG_DIR . "/presentation_svg.gp'"
PPT_HALF = PPT
PPT_QUARTER = "PPT_FIGSIZE='quarter'; load '" . GP_CONFIG_DIR . "/presentation_svg.gp'"
PPT_ONE_EIGHT = "PPT_FIGSIZE='one_eight'; load '" . GP_CONFIG_DIR . "/presentation_svg.gp'"
PPT_FULLHD = "PPT_FIGSIZE='fullhd'; load '" . GP_CONFIG_DIR . "/presentation_svg.gp'"
PPT_WITH_TITLE = "PPT_FIGSIZE='ppt_with_title'; load '" . GP_CONFIG_DIR . "/presentation_svg.gp'"


# Default interactive profile. Change this if you want gnuplot startup to default
# to @PAPER or @PPT instead.
@TYPST

Besides the .gnuplot file, there is a file that defines settings shared by all templates. That file is:

# ~/.config/gnuplot/common.gp
# Shared gnuplot defaults for all figure styles.
# Loaded by ~/.gnuplot at startup.

# Enable string-macro expansion, so commands like @TYPST and @LINESET_OKABE work.
set macros

# -----------------------------------------------------------------------------
# Fonts
# -----------------------------------------------------------------------------
# For cairo/png/svg terminals, these are resolved through fontconfig / Pango.
# In WSL, make sure the fonts are installed and visible to fontconfig.
FONT_TEXT = "STIX Two Text"
FONT_MATH = "STIX Two Math"

# -----------------------------------------------------------------------------
# Shared colors
# -----------------------------------------------------------------------------
# Catppuccin Latte-like document background and foreground colors.
C_LATTE_BG      = "#eff1f5"
C_LATTE_FG      = "#4c4f69"
C_LATTE_GRID    = "#acb0be"
C_WHITE         = "#ffffff"
C_BLACK         = "#000000"

# Named Okabe-Ito colors (first 4)
okabe_blue   = "#0072B2"
okabe_orange = "#D55E00"
okabe_green  = "#009E73"
okabe_pink   = "#CC79A7"

# -----------------------------------------------------------------------------
# Shared categorical line styles
# -----------------------------------------------------------------------------
# Default choice: Okabe-Ito. It is compact, high-contrast, and color-vision-
# deficiency friendly, so it is a safe default for papers, Typst documents,
# and presentation slides.
# Use in plotting commands with: plot ... ls 1, ... ls 2, etc.
LINESET_OKABE = "\
set linetype 1 lc rgb '#0072B2' lw 2 pt 7  ps 1.4; \
set linetype 2 lc rgb '#D55E00' lw 2 pt 13 ps 1.4; \
set linetype 3 lc rgb '#009E73' lw 2 pt 9  ps 1.4; \
set linetype 4 lc rgb '#CC79A7' lw 2 pt 11 ps 1.4; \
set linetype 5 lc rgb '#E69F00' lw 2 pt 5  ps 1.4; \
set linetype 6 lc rgb '#56B4E9' lw 2 pt 3  ps 1.4; \
set linetype 7 lc rgb '#F0E442' lw 2 pt 1  ps 1.4; \
set linetype 8 lc rgb '#000000' lw 2 pt 2  ps 1.4"

# Paul Tol's Bright qualitative scheme – the author's recommended default for
# line plots. Colour-blind safe, print-friendly, distinct on screen and paper.
# Recommended cycling order: blue, red, green, yellow, cyan, purple, grey.
# Reference: https://sronpersonalpages.nl/~pault/
LINESET_TOL_BRIGHT = "\
set linetype 1 lc rgb '#4477AA' lw 2 pt 7  ps 1.4; \
set linetype 2 lc rgb '#EE6677' lw 2 pt 5  ps 1.4; \
set linetype 3 lc rgb '#228833' lw 2 pt 9  ps 1.4; \
set linetype 4 lc rgb '#CCBB44' lw 2 pt 13 ps 1.4; \
set linetype 5 lc rgb '#66CCEE' lw 2 pt 11 ps 1.4; \
set linetype 6 lc rgb '#AA3377' lw 2 pt 3  ps 1.4; \
set linetype 7 lc rgb '#BBBBBB' lw 2 pt 1  ps 1.4; \
set linetype 8 lc rgb '#000000' lw 2 pt 2  ps 1.4"

# -----------------------------------------------------------------------------
# Catppuccin palette – accent colors only (no neutrals/grayscale)
# https://catppuccin.com/palette/
# Usage: plot sin(x) lc rgb cattpuccin_mocha_blue
# -----------------------------------------------------------------------------

# Latte
cattpuccin_latte_rosewater  = "#dc8a78"
cattpuccin_latte_flamingo   = "#dd7878"
cattpuccin_latte_pink       = "#ea76cb"
cattpuccin_latte_mauve      = "#8839ef"
cattpuccin_latte_red        = "#d20f39"
cattpuccin_latte_maroon     = "#e64553"
cattpuccin_latte_peach      = "#fe640b"
cattpuccin_latte_yellow     = "#df8e1d"
cattpuccin_latte_green      = "#40a02b"
cattpuccin_latte_teal       = "#179299"
cattpuccin_latte_sky        = "#04a5e5"
cattpuccin_latte_sapphire   = "#209fb5"
cattpuccin_latte_blue       = "#1e66f5"
cattpuccin_latte_lavender   = "#7287fd"

# Frappé
cattpuccin_frappe_rosewater = "#f2d5cf"
cattpuccin_frappe_flamingo  = "#eebebe"
cattpuccin_frappe_pink      = "#f4b8e4"
cattpuccin_frappe_mauve     = "#ca9ee6"
cattpuccin_frappe_red       = "#e78284"
cattpuccin_frappe_maroon    = "#ea999c"
cattpuccin_frappe_peach     = "#ef9f76"
cattpuccin_frappe_yellow    = "#e5c890"
cattpuccin_frappe_green     = "#a6d189"
cattpuccin_frappe_teal      = "#81c8be"
cattpuccin_frappe_sky       = "#99d1db"
cattpuccin_frappe_sapphire  = "#85c1dc"
cattpuccin_frappe_blue      = "#8caaee"
cattpuccin_frappe_lavender  = "#babbf1"

# Macchiato
cattpuccin_macchiato_rosewater = "#f4dbd6"
cattpuccin_macchiato_flamingo  = "#f0c6c6"
cattpuccin_macchiato_pink      = "#f5bde6"
cattpuccin_macchiato_mauve     = "#c6a0f6"
cattpuccin_macchiato_red       = "#ed8796"
cattpuccin_macchiato_maroon    = "#ee99a0"
cattpuccin_macchiato_peach     = "#f5a97f"
cattpuccin_macchiato_yellow    = "#eed49f"
cattpuccin_macchiato_green     = "#a6da95"
cattpuccin_macchiato_teal      = "#8bd5ca"
cattpuccin_macchiato_sky       = "#91d7e3"
cattpuccin_macchiato_sapphire  = "#7dc4e4"
cattpuccin_macchiato_blue      = "#8aadf4"
cattpuccin_macchiato_lavender  = "#b7bdf8"

# Mocha
cattpuccin_mocha_rosewater = "#f5e0dc"
cattpuccin_mocha_flamingo  = "#f2cdcd"
cattpuccin_mocha_pink      = "#f5c2e7"
cattpuccin_mocha_mauve     = "#cba6f7"
cattpuccin_mocha_red       = "#f38ba8"
cattpuccin_mocha_maroon    = "#eba0ac"
cattpuccin_mocha_peach     = "#fab387"
cattpuccin_mocha_yellow    = "#f9e2af"
cattpuccin_mocha_green     = "#a6e3a1"
cattpuccin_mocha_teal      = "#94e2d5"
cattpuccin_mocha_sky       = "#89dceb"
cattpuccin_mocha_sapphire  = "#74c7ec"
cattpuccin_mocha_blue      = "#89b4fa"
cattpuccin_mocha_lavender  = "#b4befe"

# Select the shared categorical set used by all profiles.
DEFAULT_LINESET = LINESET_OKABE
@DEFAULT_LINESET

# Shared continuous palette for maps/images.
# set palette cubehelix start 0.5 cycles -1.5 saturation 1

# -----------------------------------------------------------------------------
# Shared data/parsing defaults
# -----------------------------------------------------------------------------
set decimalsign '.'
# set datafile separator ','

# -----------------------------------------------------------------------------
# Axes styles
# -----------------------------------------------------------------------------
set ytics nomirror
set xtics nomirror

# -----------------------------------------------------------------------------
# Legend style
# -----------------------------------------------------------------------------
set key right top spacing 0.9

# -----------------------------------------------------------------------------
# Small convenience aliases
# -----------------------------------------------------------------------------
st = "set title"
sx = "set xlabel"
sy = "set ylabel"

# Optional: quick output alias, e.g. @so "figure.svg" is not valid gnuplot syntax,
# so use it as: eval so." 'figure.svg'" if you like; otherwise ignore.
so = "set output"

Slide template

The template for slide figures is the following:

# ~/.config/gnuplot/gnuplot_presentation_svg.gp
# PowerPoint / slide figure profile.
# Intended output: transparent SVG, 16:9 aspect ratio.

# Size selector. The main ~/.gnuplot aliases set PPT_FIGSIZE before loading this.
# Available values: "half", "quarter", "one_eight", "fullhd", "ppt_with_title".
if (!exists("PPT_FIGSIZE")) PPT_FIGSIZE = "half"

# --- Font-size conversion note -------------------------------------------
# A PowerPoint widescreen slide is 960 pt × 540 pt (13.33" × 7.5" at 72 pt/in).
# A fullhd SVG (1920×1080) is scaled by 0.5 when it fills the slide, so:
#   PPT visible pt = gnuplot font size × 0.5   (for fullhd variants)
# Example: gnuplot 36  →  18 pt visible in PowerPoint.
# For the half/quarter/one_eight figures the scale depends on how much of
# the slide they occupy, but they are typically used at lower magnification
# so smaller gnuplot values are appropriate.
# -------------------------------------------------------------------------


if (PPT_FIGSIZE eq "one_eight") {
    set terminal svg enhanced size 480,270 font "STIX Two Text,14" background rgb "white"
    PPT_KEY_FONT = '"STIX Two Text,13"'
} else {
if (PPT_FIGSIZE eq "quarter") {
    set terminal svg enhanced size 640,360 font "STIX Two Text,16" background rgb "white"
    PPT_KEY_FONT = '"STIX Two Text,15"'
} else {
    if (PPT_FIGSIZE eq "fullhd") {
        # 1920×1080 fills slide → scale 0.5 → gnuplot 36 ≈ 18 pt in PPT
        set terminal svg enhanced size 1920,1080 font "STIX Two Text,36" background rgb "white"
        PPT_KEY_FONT = '"STIX Two Text,34"'
    } else {
    if (PPT_FIGSIZE eq "ppt_with_title") {
        # 1920×900: leaves ~90 pt of slide height for a two-line 28 pt heading.
        # Same font calibration as fullhd (scale 0.5).
        set terminal svg enhanced size 1920,900 font "STIX Two Text,36" background rgb "white"
        PPT_KEY_FONT = '"STIX Two Text,34"'
    } else {
        set terminal svg enhanced size 960,540 font "STIX Two Text,20" background rgb "white"
        PPT_KEY_FONT = '"STIX Two Text,17"'
    }
    }
}
}


@DEFAULT_LINESET

set pointsize 1.4
# set grid back lw 1.4 lc rgb "#b8b8b8" dt 3
set border linewidth 1.8 lc rgb "black"
set tics out scale 0.9 textcolor rgb "black"
set key top right opaque box lw 1.2 spacing 1.25 width 2 samplen 1.8 \
    font @PPT_KEY_FONT textcolor rgb "black"

# Presentation notes:
# - pngcairo supports transparent PNG output via the 'transparent' terminal option.
# - If your slide background is dark, switch text/border colors to white and use
#   brighter gridlines.
# - For quarter-slide plots, use @PPT_QUARTER instead of @PPT.

Paper template

Besides templates for slides, I have a template for paper figures.

# ~/.config/gnuplot/paper_pdf.gp
# Academic paper figure profile.
# Intended output: PDF, single-column width.

# Matches paper_eps.gp: approximately 3.35 in wide. Adjust height if needed.
# PDF is an ISO-standard, open vector format and preserves searchable text and
# vector paths for typical publisher submission workflows.
set terminal pdfcairo enhanced color size 3.35in,2.35in font "STIX Two Text,9" \
    linewidth 1.0 background rgb "white"

@DEFAULT_LINESET

set pointsize 1.1
set grid back lw 0.7 lc rgb "#c9c9c9" dt 3
set border linewidth 1.0 lc rgb "black"
set tics out scale 0.55 textcolor rgb "black"
set key top right opaque box lw 0.7 spacing 1.05 width 1 samplen 1.4 \
    font "STIX Two Text,8" textcolor rgb "black"

# Paper notes:
# - Check the target journal's author instructions: use EPS only when it is
#   explicitly required, and use the required PDF version when one is stated.
# - If journal requires a different column width, change the terminal size.

Typst template

Fascinated by typst, and excited to try it out, I also built a template for typst documents.

# ~/.config/gnuplot/typst.gp
# Typst figure profile.
# Intended output: SVG, included in Typst documents compiled with --font-path.

# SVG keeps text as text and names the font; Typst/browser rendering must be able
# to find the font.
set terminal svg enhanced size 1000,700 font "STIX Two Text,16" background rgb "#eff1f5"

# Re-apply shared categorical colors after changing terminal/profile.
@DEFAULT_LINESET

set pointsize 2.1
set grid back lw 1.0 lc rgb "#acb0be"
set border linewidth 1.4 lc rgb "#4c4f69"
set tics out scale 0.8 textcolor rgb "#4c4f69"
set key top right opaque box lw 1.0 spacing 1.25 width 2 samplen 1.6 \
    font "STIX Two Text,14" textcolor rgb "#4c4f69"

# Typst/SVG notes:
# - Use enhanced text syntax for simple super/subscripts, e.g. x^{2}, a_{0}.
# - This is not real Typst/LaTeX math rendering; for that, create labels in Typst
#   or use a LaTeX-oriented terminal in a separate workflow.
# - You can try STIX Two Math in selected labels if the SVG renderer resolves it,
#   e.g. set xlabel "{/STIX Two Math:Italic k}"

However, the template is not entirely polished, and a bit bare-bones. I also had to add the STIX fonts to Typst, but I haven’t tested if it renders the gnuplot svg text correctly.

Vim template

To streamline the creation of new gnuplots, I created a small template.gp file that lives in ~/.vim/templates:

@PPT_ONE_EIGHT
unset grid

set output 'figures/{{FILENAME}}.svg'

# -------------------------- #
#          Data              #
# -------------------------- #

data_file = ""
# set datafile separator ","
# set datafile commentschars "#"

# -------------------------- #
#          Labels            #
# -------------------------- #

set title ''
@sx ''  offset 0,0.5
@sy '' offset 2,0

# -------------------------- #
#          Legend            #
# -------------------------- #

set key right top spacing 0.9 box width -2

# -------------------------- #
#           Plot             #
# -------------------------- #

plot \
    data_file using 1:2 with lines lw 2 dt 1 title "Curve 1" , \

Installation

The installation on a Linux system requires the files to be placed in the correct places. This is described in the README:

mkdir -p ~/.config/gnuplot
ln -sf "$PWD/gnuplot_common.gp" ~/.config/gnuplot/common.gp
ln -sf "$PWD/gnuplot_typst.gp" ~/.config/gnuplot/typst.gp
ln -sf "$PWD/gnuplot_paper_eps.gp" ~/.config/gnuplot/paper_eps.gp
ln -sf "$PWD/gnuplot_paper_pdf.gp" ~/.config/gnuplot/paper_pdf.gp
ln -sf "$PWD/gnuplot_presentation_svg.gp" ~/.config/gnuplot/presentation_svg.gp
ln -s  "$PWD/dot_gnuplot" ~/.gnuplot
ln -sf "$PWD/template.gp" ~/.vim/templates/