references/color_palettes.md

Scientific Color Palettes and Guidelines

Overview

Color choice in scientific visualization is critical for accessibility, clarity, and accurate data representation. This reference provides colorblind-friendly palettes and best practices for color usage.

Colorblind-Friendly Palettes

The Okabe-Ito palette is specifically designed to be distinguishable by people with all forms of color blindness.

# Okabe-Ito colors (RGB values)
okabe_ito = {
    'orange': '#E69F00',      # RGB: (230, 159, 0)
    'sky_blue': '#56B4E9',    # RGB: (86, 180, 233)
    'bluish_green': '#009E73', # RGB: (0, 158, 115)
    'yellow': '#F0E442',      # RGB: (240, 228, 66)
    'blue': '#0072B2',        # RGB: (0, 114, 178)
    'vermillion': '#D55E00',  # RGB: (213, 94, 0)
    'reddish_purple': '#CC79A7', # RGB: (204, 121, 167)
    'black': '#000000'        # RGB: (0, 0, 0)
}

Usage in Matplotlib:

import matplotlib.pyplot as plt

colors = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
          '#0072B2', '#D55E00', '#CC79A7', '#000000']
plt.rcParams['axes.prop_cycle'] = plt.cycler(color=colors)

Usage in Seaborn:

import seaborn as sns

okabe_ito_palette = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
                      '#0072B2', '#D55E00', '#CC79A7']
sns.set_palette(okabe_ito_palette)

Usage in Plotly:

import plotly.graph_objects as go

okabe_ito_plotly = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
                     '#0072B2', '#D55E00', '#CC79A7']
fig = go.Figure()
# Apply to discrete color scale

Wong Palette (Alternative for Categories)

Another excellent colorblind-friendly palette by Bang Wong (Nature Methods).

wong_palette = {
    'black': '#000000',
    'orange': '#E69F00',
    'sky_blue': '#56B4E9',
    'green': '#009E73',
    'yellow': '#F0E442',
    'blue': '#0072B2',
    'vermillion': '#D55E00',
    'purple': '#CC79A7'
}

Paul Tol Palettes

Paul Tol has designed multiple scientifically-optimized palettes for different use cases.

Bright Palette (up to 7 categories):

tol_bright = ['#4477AA', '#EE6677', '#228833', '#CCBB44',
              '#66CCEE', '#AA3377', '#BBBBBB']

Muted Palette (up to 9 categories):

tol_muted = ['#332288', '#88CCEE', '#44AA99', '#117733',
             '#999933', '#DDCC77', '#CC6677', '#882255', '#AA4499']

High Contrast (3 categories only):

tol_high_contrast = ['#004488', '#DDAA33', '#BB5566']

Sequential Colormaps (Continuous Data)

Sequential colormaps represent data from low to high values with a single hue.

Perceptually Uniform Colormaps

These colormaps have uniform perceptual change across the color scale.

Viridis (default in Matplotlib): - Colorblind-friendly - Prints well in grayscale - Perceptually uniform

plt.imshow(data, cmap='viridis')

Cividis: - Optimized for colorblind viewers - Designed specifically for deuteranopia/protanopia

plt.imshow(data, cmap='cividis')

Plasma, Inferno, Magma: - Perceptually uniform alternatives to viridis - Good for different aesthetic preferences

plt.imshow(data, cmap='plasma')

When to Use Sequential Maps

  • Heatmaps showing intensity
  • Geographic elevation data
  • Probability distributions
  • Any single-variable continuous data (low → high)

Diverging Colormaps (Negative to Positive)

Diverging colormaps have a neutral middle color with two contrasting colors at extremes.

Colorblind-Safe Diverging Maps

RdYlBu (Red-Yellow-Blue):

plt.imshow(data, cmap='RdYlBu_r')  # _r reverses: blue (low) to red (high)

PuOr (Purple-Orange): - Excellent for colorblind viewers

plt.imshow(data, cmap='PuOr')

BrBG (Brown-Blue-Green): - Good colorblind accessibility

plt.imshow(data, cmap='BrBG')

Avoid These Diverging Maps

  • RdGn (Red-Green): Problematic for red-green colorblindness
  • RdYlGn (Red-Yellow-Green): Same issue

When to Use Diverging Maps

  • Correlation matrices
  • Change/difference data (positive vs. negative)
  • Deviation from a central value
  • Temperature anomalies

Special Purpose Palettes

For Genomics/Bioinformatics

Sequence type identification:

# DNA/RNA bases
nucleotide_colors = {
    'A': '#00CC00',  # Green
    'C': '#0000CC',  # Blue
    'G': '#FFB300',  # Orange
    'T': '#CC0000',  # Red
    'U': '#CC0000'   # Red (RNA)
}

Gene expression: - Use sequential colormaps (viridis, YlOrRd) for expression levels - Use diverging colormaps (RdBu) for log2 fold change

For Microscopy

Fluorescence channels:

# Traditional fluorophore colors (use with caution)
fluorophore_colors = {
    'DAPI': '#0000FF',      # Blue - DNA
    'GFP': '#00FF00',       # Green (problematic for colorblind)
    'RFP': '#FF0000',       # Red
    'Cy5': '#FF00FF'        # Magenta
}

# Colorblind-friendly alternatives
fluorophore_alt = {
    'Channel1': '#0072B2',  # Blue
    'Channel2': '#E69F00',  # Orange (instead of green)
    'Channel3': '#D55E00',  # Vermillion
    'Channel4': '#CC79A7'   # Magenta
}

Color Usage Best Practices

Categorical Data (Qualitative Color Schemes)

Do: - Use distinct, saturated colors from Okabe-Ito or Wong palette - Limit to 7-8 categories max in one plot - Use consistent colors for same categories across figures - Add patterns/markers when colors alone might be insufficient

Don't: - Use red/green combinations - Use rainbow (jet) colormap for categories - Use similar hues that are hard to distinguish

Continuous Data (Sequential/Diverging Schemes)

Do: - Use perceptually uniform colormaps (viridis, plasma, cividis) - Choose diverging maps when data has meaningful center point - Include colorbar with labeled ticks - Test appearance in grayscale

Don't: - Use rainbow (jet) colormap - not perceptually uniform - Use red-green diverging maps - Omit colorbar on heatmaps

Testing for Colorblind Accessibility

Online Simulators

  • Coblis: https://www.color-blindness.com/coblis-color-blindness-simulator/
  • Color Oracle: Free downloadable tool for Windows/Mac/Linux
  • Sim Daltonism: Mac application

Types of Color Vision Deficiency

  • Deuteranopia (~5% of males): Cannot distinguish green
  • Protanopia (~2% of males): Cannot distinguish red
  • Tritanopia (<1%): Cannot distinguish blue (rare)

Python Tools

# Using colorspacious to simulate colorblind vision
from colorspacious import cspace_convert

def simulate_deuteranopia(image_rgb):
    from colorspacious import cspace_convert
    # Convert to colorblind simulation
    # (Implementation would require colorspacious library)
    pass

Implementation Examples

Setting Global Matplotlib Style

import matplotlib.pyplot as plt
import matplotlib as mpl

# Set Okabe-Ito as default color cycle
okabe_ito_colors = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
                     '#0072B2', '#D55E00', '#CC79A7']
mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=okabe_ito_colors)

# Set default colormap to viridis
mpl.rcParams['image.cmap'] = 'viridis'

Seaborn with Custom Palette

import seaborn as sns

# Set Paul Tol muted palette
tol_muted = ['#332288', '#88CCEE', '#44AA99', '#117733',
             '#999933', '#DDCC77', '#CC6677', '#882255', '#AA4499']
sns.set_palette(tol_muted)

# For heatmaps
sns.heatmap(data, cmap='viridis', annot=True)

Plotly with Discrete Colors

import plotly.express as px

# Use Okabe-Ito for categorical data
okabe_ito_plotly = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
                     '#0072B2', '#D55E00', '#CC79A7']

fig = px.scatter(df, x='x', y='y', color='category',
                 color_discrete_sequence=okabe_ito_plotly)

Grayscale Compatibility

All figures should remain interpretable in grayscale. Test by converting to grayscale:

# Convert figure to grayscale for testing
fig.savefig('figure_gray.png', dpi=300, colormap='gray')

Strategies for grayscale compatibility: 1. Use different line styles (solid, dashed, dotted) 2. Use different marker shapes (circles, squares, triangles) 3. Add hatching patterns to bars 4. Ensure sufficient luminance contrast between colors

Color Spaces

RGB vs CMYK

  • RGB (Red, Green, Blue): For digital/screen display
  • CMYK (Cyan, Magenta, Yellow, Black): For print

Important: Colors appear different in print vs. screen. When preparing for print: 1. Convert to CMYK color space 2. Check color appearance in CMYK preview 3. Ensure sufficient contrast remains

Matplotlib Color Spaces

# Save for print (CMYK)
# Note: Direct CMYK support limited; use PDF and let publisher convert
fig.savefig('figure.pdf', dpi=300)

# For RGB (digital)
fig.savefig('figure.png', dpi=300)

Common Mistakes

  1. Using jet/rainbow colormap: Not perceptually uniform; avoid
  2. Red-green combinations: ~8% of males cannot distinguish
  3. Too many colors: More than 7-8 becomes difficult to distinguish
  4. Inconsistent color meaning: Same color should mean same thing across figures
  5. Missing colorbar: Always include for continuous data
  6. Low contrast: Ensure colors differ sufficiently
  7. Relying solely on color: Add texture, patterns, or markers

Resources

  • ColorBrewer: http://colorbrewer2.org/ - Choose palettes by colorblind-safe option
  • Paul Tol's palettes: https://personal.sron.nl/~pault/
  • Okabe-Ito palette origin: "Color Universal Design" (Okabe & Ito, 2008)
  • Matplotlib colormaps: https://matplotlib.org/stable/tutorials/colors/colormaps.html
  • Seaborn palettes: https://seaborn.pydata.org/tutorial/color_palettes.html
← Back to scientific-visualization