Design Matters

a rant by daniel roelfs

Prologue

Bad design is innate to science

Nature - The design decisions behind Nature’s new look (2019)
Reply to a tweet by Dan Quintana
Reply from prof. Brian Cox to comments from Comis Sans designer Vincent Connare
Picture of Evard Moser's presentation at the NordicAIMeet 2021 (source, 1 Nov. 2021)
literally any poster session ever

Slide title

Slide 1
<basic design principles>

Chapter 1

Scientific posters

I don't want to talk about scientific posters

Poster sessions suck

Resources

Chapter 2

"I don't care about design"

- No one ever
"But whether something is nice or pretty is subjective!"
Art can be subjective, but design is either good or bad at serving a purpose
and the ability to serve its purpose can be measured
"So I should care about design, but why invest time in making it look pretty too"
People like looking at pretty things

Case in point: the entire field or marketing, advertising, interior design, ...

Which do you want in your house?

Monobloc chair
Gudmundur Ludvik - Close dinnertable chair
BaZ - Abschied von Plastikstühlen ("Farewell to the plastic chair", 2008)

Which looks more appealing?

UK plain packaging for cigarettes
Malboro cigarette packet

Which looks more trustworthy?

AMC website in 2005
AMC website in 2021

What about these?

Gapminder figure in default ggplot style
Gapminder figure with better style and accessible colors
We'll go over how to go from left to right later
FHI's UngVoksen newsletter uses figure with default ggplot theme (source)

Efficient communication

Science interacts with

  • Educators
  • Journalists
  • Policymakers
  • etc.
  • Journal editors
  • Reviewers
  • Grant agencies
How many of these will read and understand your paper? You want to keep them happy

Why does it matter?

  • Academics are people too, people like looking at nice things
  • Good and clear figures or illustrations are part of science communication
  • People remember visuals better than text
  • Succeeding at explaining 1 thing > failing to explain 10 things
Low cost, low reward
High cost, high reward
Paper on the influence of graphic design on science communication (source)

Chapter 3

Presentations

  • More people will see your presentations than your posters
  • More people you care about will see your presentations
  • Presentations have higher return on investment
  • So let's talk about how to improve presentations
Be nice to your scientist
Slide on cognitive load demanding a lot of cognitive load (source)
Same slide redesigned

Illustrations

Replace text with illustrations wherever you can

Illustrations

  • Time spent is an investment
  • Provides visual aid to explain complex concepts and methods
  • Can be reused for manuscripts and grant applications

Illustrations improve grant applications

Ida talking about how figures improve grant applications (shared with permission)
Dan talking about how figures improve grant applications (shared with permission)

Take it to the next level

PowerPoint free at university, frustrating
InkScape free, open source, not great
Adobe Illustrator
Adobe InDesign
$$$, free at university virtual
desktop
Affinity Designer
Affinity Publisher
$, lifetime license

Aspect ratio

Maximize the space available
Black bars on either side when the slideshow doesn't match screen size
"1 minute per slide" is outdated

Margins

Decent margins, room to breathe
Tight margins, claustrophobic

Alignment

Left alignment
Center alignment
  • Be more lazy
  • Keep it simple, stupid
  • Less is more
Award winning poster at 23rd ETH-Conference on Combustion Generated Nanoparticles 2019
Award winning poster from Elleke Tissink at WCPG 2021

Chapter 4

The devil is in the details

Case study: typefaces & fonts

Arial and Comic Sans are universally disliked among designers (source, source)
Helvetica isn't much liked either

Arial sucks

Arial 👎
Poppins 👍

Context matters

Font choices matter, Copperplate looks cheap for a law firm and too expensive for a kindergarten

Typeface sends a message

What type or genre of movie do you associate with each of these title cards

Choose wisely

Fonts with a ★ are plausible for body text

Best of Google Fonts

  • Open Sans
  • Roboto
  • Poppins (body font for this presentation )
  • Lato (header font for this presentation)
  • Alegreya
  • Montserrat
  • Raleway
  • Merriweather
Every letter you've ever read is the consequence of a design choice ...except if you read Arial or Helvetica (also Calibri or Verdana) The devil is in the details

Chapter 5

Colors are complicated

XKCD - Painbow Award (2537)
Colors influence your emotional reaction (image source, source)
Fabio Crameri et al. - The misuse of colour in science communication, Nature Communications (2020)
Color discrepancy between jet or rainbow color palette and scientific colors (source)
Fabio Crameri - Scientific Color Maps
Fabio Crameri - Guideline for choosing the right scientific colour map (source)

Chapter 6

Figures (with code 👍)

How do I read a paper?

  1. Skim the paper
  2. Look at the figures
  3. Read the abstract
  4. Read the results and conclusion
  5. Read the entire paper
  • Figures draw readers into a manuscript
  • Figures are re-usable
  • Scripts to create figures are re-usable
  • Creating nice figures for your manuscript is an investment

how to use scientific colors in {ggplot2}


								library(normentR)

								penguins %>%
								  ggplot(aes(x = bill_length_mm, y = body_mass_g, 
								  		        color = species)) +
								  geom_point(size = 2) + 
								  scale_color_norment(discrete = TRUE, 
								    							  palette = "batlow") + 
								  theme_norment(base_size = 9)
								

								library(scico)
																
								penguins %>%
								  ggplot(aes(x = bill_length_mm, y = body_mass_g, 
								  		        color = species)) +
								  geom_point(size = 2) + 
								  scale_color_scico_d(palette = "batlow") +
								  theme_minimal(base_size = 9)
								

theme_minimal() is your friend


								penguins %>%
								  ggplot(aes(x = bill_length_mm, y = body_mass_g, 
								  		        color = species)) +
								  geom_point(size = 2) + 
								  scale_color_norment(discrete = TRUE, 
								    							  palette = "batlow") + 
								  theme_minimal()
								

My setup


								### CREATE SCATTER PLOT ########################

								#-- Libraries -------------------------

								library(tidyverse)
								library(ggtext)
								library(scico)
								library(patchwork)

								#-- Load data ------------------------

								...
							

My setup


								### RUN XGBOOST ANALYSIS ########################

								# -- Libraries -------------------------
								
								import numpy as np
								import pandas as pd
								import matplotlib.pyplot as plt

								# -- Load data -------------------------

								...
							

									data %>% 
									  ggplot(aes(x = gdpPercap, y = lifeExp, 
									             size = pop)) +
									  geom_point(aes(color = continent)) + 
									  geom_smooth(method = "lm") +
									  scale_x_log10()
								

									data %>% 
									  ggplot(aes(x = gdpPercap, y = lifeExp, 
									             size = pop)) +
									  geom_point(aes(color = continent)) + 
									  geom_smooth(method = "lm", show.legend = FALSE) +
									  scale_x_log10() + 
									  theme_minimal() + 
									  theme(panel.grid = element_line(colour = "grey90"))
								

									data %>% 
									  ggplot(aes(x = gdpPercap, y = lifeExp, 
									             size = pop)) +
									  geom_point(aes(color = continent), alpha = 0.5, stroke = 0) + 
									  geom_smooth(method = "lm", color = "grey30", 
									              alpha = 0.15, show.legend = FALSE) +
									  labs(title = "Relation between GDP and life expectancy",
									       x = "GDP per capita",
									       y = "Life expectancy",
									       color = "Continent",
									       size = "Population") +
									  scale_x_log10() + 
									  scale_color_scico_d(palette = "batlow") +
									  scale_size_continuous(range = c(1,15), labels = scales::label_number(),
									                        guide = guide_legend(label.position = "bottom") + 
									  theme_minimal() + 
									  theme(plot.title = element_markdown(size = 14),
									        legend.box = "vertical",
									        legend.position = "bottom",
									        panel.grid = element_line(colour = "grey90")
									  )
								
The monstrosity you can make with all {ggplot2} theme() options (based on a gist by Emily Riederer)

								ggplot(data, aes(x = x, y = y, col = as_factor(x))) + 
								geom_point(size = 5) + 
								labs(title = "test title",
								     subtitle = "test subtitle",
								     x = "my x axis",
								     y = "my y axis",
								     caption = "this is a caption",
								     col = "Renamed Legend") +
								facet_grid(w ~ z, switch = "y") +
								theme(
									plot.background = element_rect(fill = "lightyellow"),
									plot.title = element_text(size = 30, hjust = 0.25),
									plot.subtitle = element_text(size = 20, hjust = 0.75, color = "mediumvioletred", family = "serif"),
									plot.caption = element_text(size = 10, face = "italic", angle = 25),

									panel.background = element_rect(fill = "lightblue", colour = "darkred", size = 4),
									panel.border = element_rect(fill = NA, color = "green", size = 2),
									panel.grid.major.x = element_line(color = "purple", linetype = 2),
									panel.grid.minor.x = element_line(color = "orange", linetype = 3),
									panel.grid.minor.y = element_blank(),

									axis.title.x = element_text(face = "bold.italic", color = "blue"),
									axis.title.y = element_text(family = "mono", face = "bold", size = 20, hjust = 0.25),
									axis.text = element_text(face = "italic", size = 15),
									axis.text.x.bottom = element_text(angle = 180), # note that axis.text options from above are inherited

									strip.background = element_rect(fill = "magenta"),
									strip.text.y = element_text(color = "white"),
									strip.placement = "outside",

									legend.background = element_rect(fill = "orangered4"), # generally will want to match w plot background
									legend.key = element_rect(fill = "orange"),
									legend.direction = "horizontal",
									legend.position = "bottom",
									legend.justification = "left",
									legend.title = element_text(family = "serif", color = "white"),
									legend.text = element_text(family = "mono", face = "italic", color = "limegreen")
								)
							

One quick word on file organization


								$ pwd
								/Users/dtroelfs/Dropbox/NORMENT/r_scripts/ica_genetics
								$ tree
								./
								├── convert_pleio_results.m
								├── compare_ic_modelorders.R
								├── create_fuma_table.R
								├── create_manhattan_figure.R
								├── extract_pleio_qq_data.ipynb
								├── extract_ukb_questionnaire_fields.R
								├── figures/
								│   ├── ica_weightmatrix.png
								│   ├── ic_heritability.png
								│   ├── ic_manhattan_plots.png
								│   ├── icxic_ldsc_matrix.png
								│   └── questionscores_distribution.png
								├── files/
								│   ├── fuma_job_names.txt
								│   ├── ica_loadings.txt
								│   ├── ldsc_stats.txt
								│   ├── question_definitions.txt
								│   └── sumstats/
								│       ├── GWAS_ICA_1.sumstats.gz
								│       └── GWAS_ICA_2.sumstats.gz
								├── ica_genetics.Rproj
								├── plot_heritability.R
								├── plot_ica_weight_matrix.R
								├── plot_icxic_ldsc_matrix.R
								└── plot_questionnaire_scores.R
								
								3 directories, 21 files
							

… on coding style


								### PLOT ICA WEIGHT MATRIX ########################
							
								#-- Libraries -------------------------
							
								library(tidyverse)
								
								#-- Load data ------------------------
								
								data <- read_csv("files/ica_loadings.txt") %>%
								  janitor::clean_names()
								
								#-- Wrangle data ------------------------
								
								data <- data %>%
								  mutate(diagnosis = str_to_upper(diagnosis))
							
								#-- Create plot ------------------------
							
								data %>%
								  pivot_longer(cols = starts_with("ic"), names_to = "ic", values_to = "loading") %>%
								  mutate(ic = fct_reorder(ic, parse_number(ic))) %>%
								  ggplot(aes(x = ic, y = question, fill = loading)) +
								  geom_tile()
							

Epilogue

Some basic rules for better design

KISS

Keep It Simple, Stupid

Color scheme

When in doubt, go for greyscale e.g.
  • Black on white (when presenting in a bright room)
  • Light grey on black (when presenting in a darkened room)

Fonts

Don't use Comic Sans or Arial, ever!
List of good and bad fonts (from Butterick's Practical Typography)

Line length

Length of a single line should be between 40-60 characters
Optimal line length to maximize readability (source, source, source)

Dynamic figure design

Presenting on Zoom

Don't use 4x3 aspect ratio when presenting on Zoom
Black bars on either side when the slideshow doesn't match screen size

NORMENT template

The original NORMENT template is outdated
Link to the new templates. Disclaimer: I created the new NORMENT template

Abstraction

Get rid of everything that doesn't aid in delivering the message
Abtract-o-meter to illustrate concept of abstraction by designer Christopher Niemann

Priorities

Data goes before aesthetics

Final rule

Trust your gut

Resources

Design in this presentation

Get creative

Thank you!