Skip to the content.

PennLINC Figure Making Guide

Table of Contents

In this tutorial, we’ll go over some general figure design principles, then outline more specific guidelines for PennLINC. To make it convenient, reproducible and easy, we also go over a workflow and readily available scripts that can format all your plots (along with font type and size) automatically for you in Python and R.

Let’s dive in!

FIGURE DESIGN PRINCIPLES

Summarized from slides by Golia Shafiei, Ph.D. (based on the book “The Visual Display of Quantitative Information” by Edward R. Tufte [1])

Key guiding principles can help tailor figures across types

  1. Above all else, show the data
  2. Reduce “chart junk” — borders, shadows, 3-D versions when 2-D would suffice, grid lines, tick marks
  3. Maximize data-to-ink ratio and erase redundant data-ink. EXAMPLE of high data-ink ratio (and chart junk) on the left, and low data-ink ratio on the right:
  4. Create the simplest graph that conveys the information you want to present
  5. Don’t overcomplicate figures—they are tools for understanding. Every bit of ink requires a reason.

(figures from [2])

Additional Tips, Tricks, and Recommendations

  1. Use color-blind friendly palettes when possible, especially ones that work in both color and grey scale.
    1. Online resources for simulating colorblindeness can help with this, or fully de-saturating plots within Illustrator, In Design, or other tools.
    2. Avoid maps with uneven color gradients (e.g., Jet)
  2. Avoid pie charts—tables are almost always better
  3. Use meaningful baseline numbers for axes to avoid distorting data interpretation. EXAMPLE: lack of meaningful baseline numbers on the left.

(figures from [2])

  1. Use visual variables (color, shape, shade) only to identify data variation
  2. Be consistent with visual variables—e.g., don’t use different colors to represent the same kinds of data. EXAMPLE: visual variables can help readers interpret figures when used appropriately.

(figures from [3])

  1. Use a page layout to decide if the figure is a 1-column (full page width) figure or a two column (half-page width) figure. Example: A full-page width figure.

(figures from [3])

  1. Limit the number of fonts and font sizes in the figure. Check journal guidelines and match the figure font to the font the journal prints in.
  2. Most figure-specific changes can be implemented in code, but In Design and/or Illustrator can be helpful for finishing touches.
  3. Shared figure-plotting code can simplify incorporating these recommendations!

PENNLINC SPECIFIC GUIDELINES

Core visual default parameters

Statistics

Captions

Export & file handling

Pre-submission figure checklist

Plotting on the brain / surface

Tools for plotting on the brain surface

Python

R

RESOURCES

Colormaps

Stock images

HOW TO IMPLEMENT THIS IN A REPRODUCIBLE WAY: FIGURE FORMATTING UTILITIES

The problem

Pretty much all researchers will face it at some point: you need to create a multipanel figure for a manuscript. In doing so, you might first generate various plots that you then import into a software tool like InDesign or Illustrator. This is especially true when your panels aren’t all aligned, or contain various file types: maybe some are svg files containing graphs, some are png files containing brain images, etc.

In the process of creating this multipanel figure, you typically end up needing to resize and adjust so that all panels are arranged the way you want. However, this process also rescales the font size of the plots, leading to panels with inconsistent font sizes (yikes!).

This means you then need to manually tweak font sizes after the fact in InDesign (or Illustrator), or do a lot of trial and error when specifying plot sizes in Python or R to finally get a plot that has the right font size when imported into InDesign — not ideal 🫠.

The solution

Rather than manual tweaking or guessing figure sizes over and over, we can use a few functions that will enforce figure formatting for us.

The figure formatting repository contains scripts for creating figures with exact physical dimensions in R and Python. Specifically, the repo contains the following:

Specifically, here’s what the functions do:

Requirements

In Python:

Install with:

pip install matplotlib

In R:

Install with:

install.packages(c("ggplot2", "cowplot"))

Workflow

Let’s say you’ve conducted your main analyses and have some key result plots in hand. It’s now time to format them for a manuscript submission! Below are a few easy steps to follow when formatting figures for manuscripts.

1. Create a figure layout

The best way to approach this is to start by outlining the layout of your multipanel figure in your preferred software tool (InDesign, Illustrator, Inkscape, etc.). When creating this layout, be sure to check the figure guidelines of the journal where you’re planning to submit the paper. In this tutorial, we’ll work with the Nature portfolio guidelines (found here). A multipanel figure layout might look something like this:

✨ For convenience, the repo contains templates for multipanel figures:

You can download these here.

Note: make sure to set/switch the page dimension units to millimeters; this is because journals most often specify their requirements in mm, and will be convenient when generating figures below. To do this, right-click on the rulers and set them to mm.

Note: check out this tutorial for more detailed information on how to create multipanel figure layouts in InDesign!

2. Generate figures

Next, for each plot within the layout you just created, note the figure dimensions in millimeters. For example, let’s say we have a scatterplot we’d like to output with a width of 80mm, and a height of 60mm.

Go back to the script that generates your plot and use the figure formatting and saving functions to generate the plot in these specific dimensions.

Note: the examples below are for single plots. For plot grids and more examples, see example_figure_formatting.py and example_figure_formatting.R.

Python 🐍

Here’s what that might look like in Python.

First, add figure_formatting.py to your Python path. You have two options:

  1. Clone the repository:
    cd /path/to/your/scripts
    git clone https://github.com/PennLINC/figure_formatting.git
    

    This will create a figure_formatting directory in your current location.

  2. Download the script directly:
    • Download Python/figure_formatting.py from the GitHub repository
    • Place it in your workspace directory (or a subdirectory)

Then, in your Python script that generates the result plot (in your workspace directory), import the functions:

import sys
from pathlib import Path

# Add the directory containing figure_formatting.py to your path
# Option 1: If you cloned the repo to a sibling directory
sys.path.insert(0, str(Path(__file__).parent.parent / "figure_formatting" / "Python"))

# Option 2: If you downloaded figure_formatting.py to your workspace directory
sys.path.insert(0, str(Path(__file__).parent))  # if in same directory

# Option 3: If you placed it in a specific location, use the full path:
sys.path.insert(0, "/path/to/directory/containing/figure_formatting.py")

from figure_formatting import setup_figure, save_figure
import matplotlib.pyplot as plt
import numpy as np

Finally, use the figure formatting functions to generate your plot in the desired dimensions:

# First, initiate your figure with specified dimensions
# Default font: Helvetica, 7pt (can be customized with base_pt, label_pt, title_pt, sans_list parameters)
fig, ax = setup_figure(width_mm=80, height_mm=60, 
  margins_mm=(1, 1, 1, 1)) # optional, add some margins if you want more white space around the plot

# Then generate your plot (simulated scatterplot here)
x = np.random.randn(100)
y = np.random.randn(100)
ax.scatter(x, y, s=20, alpha=0.6)
ax.set_xlabel('X axis label')
ax.set_ylabel('Y axis label')
ax.set_title('My Plot')

# Save with exact dimensions
save_figure(fig, 'my_plot.svg')
plt.close(fig)

R 🦁

Here’s what this might look like in R.

First, add figure_formatting.R to your R path. You have two options:

  1. Clone the repository:
    cd /path/to/your/scripts
    git clone https://github.com/PennLINC/figure_formatting.git
    

    This will create a figure_formatting directory in your current location.

  2. Download the script directly:
    • Download R/figure_formatting.R from the GitHub repository
    • Place it in your workspace directory (or a subdirectory)

Then, in your R script that generates the result plot (in your workspace directory), source the functions:

# Add the directory containing figure_formatting.R to your path
# Option 1: If you cloned the repo to a sibling directory
source("../figure_formatting/R/figure_formatting.R")

# Option 2: If you downloaded figure_formatting.R to your workspace directory
source("figure_formatting.R")  # if in same directory

# Option 3: If you placed it in a specific location, use the full path:
source("/path/to/directory/figure_formatting.R")

library(ggplot2)

Finally, use the figure formatting functions to generate your plot in the desired dimensions:

# First, initiate your figure with specified dimensions
# Default font: Arial (sans-serif), 7pt (can be customized with base_pt, label_pt, title_pt, font_type parameters)
width = 80
height = 60
fig_setup <- setup_figure(width_mm = width, height_mm = height)

# Then generate your plot (simulated scatterplot here)
set.seed(42)
data <- data.frame(
  x = rnorm(100),
  y = rnorm(100)
)
p <- ggplot(data, aes(x = x, y = y)) +
  geom_point(size = 2, alpha = 0.6) +
  labs(x = "X axis label", y = "Y axis label", title = "My Plot") +
  fig_setup$theme_obj # this applies the figure formatting 

# Save with exact dimensions
save_figure(p, "my_plot.svg", width_mm = width, height_mm = height)

3. Load the plot into the figure layout

The last step is just to load your plot file (e.g., svg or other; can also be brain pngs for example) into the figure layout from InDesign (or other). To do this in InDesign, simply select the rectangle frame you prepared for this plot:

Next, import the plot file - et voilà! The figure will have the exact dimensions you’ve specified.

An additional nice feature here is that InDesign will automatically remember the path to this file, and will update the plot whenever you regenerate it in R/Python.

Then just use these formatting functions for the rest of your plots! 😊

Note: when saving the multipanel figure you created in InDesign, it might throw a warning that a font wasn’t found for some plots in the page. Just click ok and ignore that! It will save just fine.

QUESTIONS AND TROUBLESHOOTING

If you have any questions or need help troubleshooting, feel free to write in the #pennlinc_docs channel on Slack!

REFERENCES

[1] Tufte, E. R., & Graves-Morris, P. R. (1983). The visual display of quantitative information (Vol. 2, No. 9). Cheshire, CT: Graphics press.

[2] Few, S. (2011). The chartjunk debate: A close examination of recent findings. Visual Business Intelligence Newsletter. Perceptual Edge.

[3] Shafiei, G., Fulcher, B. D., Voytek, B., Satterthwaite, T. D., Baillet, S., & Misic, B. (2023). Neurophysiological signatures of cortical micro-architecture. Nature communications, 14(1), 6000.