Automating Plot Generation with gnuplot and ScriptsAutomating plot generation saves time, ensures reproducibility, and scales visualization workflows. gnuplot — a compact, scriptable plotting utility available on Linux, macOS, and Windows — is ideal for batch plotting and integration with other tools. This article walks through principles, practical examples, integrations, and best practices for automating plot creation using gnuplot and scripts.
Why automate plotting?
Automated plotting is valuable when you need to:
- Reproduce figures consistently across runs and datasets.
- Generate hundreds or thousands of plots without manual intervention.
- Integrate plotting into data-processing pipelines (ETL, nightly jobs, CI).
- Produce publication-quality figures with consistent style and metadata.
gnuplot is well-suited because it:
- Accepts commands from files or standard input.
- Supports many output formats (PNG, SVG, PDF, EPS, LaTeX-compatible).
- Can be called from shell scripts, Python, R, Makefiles, and CI systems.
- Has powerful data transformation and formatting options built in.
Basic gnuplot script structure
A gnuplot script is a plain text file containing gnuplot commands. Typical structure:
- Set terminal/output options (format, size, font).
- Set labels, ranges, style settings, and key/legend.
- Load or plot data using plot/splot commands.
- Optionally, save or reset settings.
Example (save as plot.gnuplot):
set terminal pngcairo size 800,600 enhanced font 'DejaVu Sans,12' set output 'output.png' set title 'Sample Data' set xlabel 'X' set ylabel 'Y' set grid plot 'data.csv' using 1:2 with lines title 'Series A'
Run from shell:
gnuplot plot.gnuplot
Embedding variables and templates
For automation you often need to inject variables (filenames, ranges, titles). Methods:
- Use gnuplot’s string handling and
system()
if needed. - Generate the gnuplot script dynamically from a template using a scripting language (bash, Python, Perl).
- Use command-line
-e
to pass simple variable assignments.
Example (bash template generation):
#!/bin/bash DATAFILE="$1" OUTFILE="${2:-output.png}" TITLE="${3:-My Plot}" cat > tmp.gnuplot <<EOF set terminal pngcairo size 1000,600 enhanced font 'DejaVu Sans,12' set output '${OUTFILE}' set title '${TITLE}' set xlabel 'X' set ylabel 'Y' plot '${DATAFILE}' using 1:2 with lines lw 2 title 'Series' EOF gnuplot tmp.gnuplot rm tmp.gnuplot
Example (passing vars with -e):
gnuplot -e "datafile='data.csv'; outfile='out.png'; title='Auto Plot'" - <<'GNUPLOT' set terminal pngcairo size 800,600 set output outfile set title title plot datafile using 1:2 with lines GNUPLOT
Generating multiple plots in batches
Common tasks:
- Plot multiple columns from one file into separate images.
- Plot many files with consistent styles.
- Produce time series snapshots (one plot per timestamp).
Bash loop example (plot each column separately):
#!/bin/bash DATA=data.csv N_COLS=4 for col in $(seq 2 $N_COLS); do outfile="col${col}.png" gnuplot -e "datafile='${DATA}'; col=${col}; outfile='${outfile}'" - <<'GP' set terminal pngcairo size 800,600 set output outfile set title sprintf('Column %d', col) plot datafile using 1:col with lines title columnheader(col) GP done
If you prefer a single gnuplot script that loops internally, use gnuplot’s iteration:
DATA='data.csv' do for [col=2:4] { set output sprintf('col%d.png', col) plot DATA using 1:col with lines title columnheader(col) }
Producing multi-panel figures and layouts
gnuplot supports multiplot mode for arranging several subplots into a single output. Example 2×2 layout:
set terminal pngcairo size 1200,900 set output 'multipanel.png' set multiplot layout 2,2 title 'Multi-panel Example' do for [col=2:5] { set title sprintf('Column %d', col) plot 'data.csv' using 1:col with lines } unset multiplot
For publication-quality composite figures, combine gnuplot’s EPS/PDF output with LaTeX or use SVG outputs and an external vector editor.
Styling and consistent themes
Create a style header script to reuse in all plots:
# style.gnuplot set terminal pngcairo enhanced font 'DejaVu Sans,11' set grid lt 1 lc rgb '#dddddd' set key right top set style line 1 lw 2 lc rgb '#1f77b4' set style line 2 lw 2 lc rgb '#ff7f0e'
Include via:
load 'style.gnuplot'
Use set format
to control axis tick formatting and set xtics
/ytics
for custom ticks.
Data preprocessing and piping
For complex transformations, preprocess data in a script (awk, Python, R) and pipe to gnuplot. Example: compute moving average with awk then plot:
awk 'NR>1{sum+=$2; buf[NR%5]=$2; if(NR>5) sum-=buf[(NR+5)%5]; if(NR>=5) print $1, sum/5}' data.csv | gnuplot -p -e "plot '-' using 1:2 with lines title '5-pt MA';"
Alternatively, call gnuplot from Python using subprocess and pass data via stdin.
Integrating with other languages and tools
- Python: Use subprocess to call gnuplot or write gnuplot files. For tighter integration, use matplotlib for advanced styling but gnuplot is lighter for quick numeric-driven plots.
- R: System calls or write gnuplot scripts from R. R’s ggplot2 may be preferable for layered grammar, but gnuplot excels in portability and scriptability.
- Makefile/CI: Include a rule that creates plots as build artifacts; run on changes to data or scripts.
Makefile example:
plots: plot1.png plot2.png plot1.png: data.csv plot1.gnuplot gnuplot plot1.gnuplot plot2.png: data.csv plot2.gnuplot gnuplot plot2.gnuplot
Export formats and LaTeX integration
Common terminals:
- pngcairo — high-quality PNG with anti-aliasing.
- svg — scalable vector, good for web.
- pdfcairo / eps — publication vector formats.
- epslatex / cairolatex — split text for LaTeX rendering (useful for font consistency in papers).
Example using epslatex:
set terminal epslatex color size 4,3 standalone set output 'figure.tex' plot 'data.csv' using 1:2 with lines
Then compile with LaTeX to get a vector PDF.
Error handling and logging
- Check gnuplot exit codes in scripts.
- Redirect stderr/stdout to log files for debugging.
- Use small test datasets when developing scripts.
Example:
gnuplot script.gnuplot 2> gnuplot.log || { echo "gnuplot failed — check gnuplot.log"; exit 1; }
Best practices
- Keep style settings in reusable files and load them.
- Use clear variable names when templating scripts.
- Prefer vector formats for publication and PNG/SVG for web.
- Pin fonts and sizes for consistent cross-platform appearance.
- Version-control your gnuplot scripts and generated plots’ source templates.
- Add metadata (titles, captions) programmatically if generating many images.
Example: full automation pipeline
- Preprocess raw CSVs with Python (clean, aggregate).
- For each processed CSV, generate a gnuplot script from a Jinja2 template.
- Run gnuplot in parallel (GNU parallel or xargs -P) to render images.
- Combine or post-process (ImageMagick for thumbnails, pdftk for PDF merging).
- Upload artifacts to web or archive.
Snippet (Python subprocess example):
import subprocess, pathlib for csv in pathlib.Path('processed').glob('*.csv'): out = csv.with_suffix('.png').name script = f""" set terminal pngcairo size 1200,800 set output '{out}' set title '{csv.stem}' plot '{csv}' using 1:2 with lines lw 2 """ subprocess.run(['gnuplot'], input=script.encode())
Troubleshooting common issues
- Fonts look different: specify font family and size explicitly and ensure the font is installed.
- Data parsing errors: ensure delimiters and headers are handled; use
using
andfirstrow
/skip
options. - Slow rendering: reduce image size, simplify styles, or switch terminals.
- Legends/clipping: adjust margins with
set lmargin
/rmargin
/tmargin
/bmargin
.
Automating plots with gnuplot and scripts provides a lightweight, reproducible, and flexible approach to visualization. With templating, batching, and integration into pipelines, you can reliably produce consistent figures for monitoring, reporting, and publication.
Leave a Reply