Initial commit for scientific-visualization
This commit is contained in:
348
references/color_palettes.md
Normal file
348
references/color_palettes.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# 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
|
||||
|
||||
### Okabe-Ito Palette (Recommended for Categories)
|
||||
|
||||
The Okabe-Ito palette is specifically designed to be distinguishable by people with all forms of color blindness.
|
||||
|
||||
```python
|
||||
# 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:**
|
||||
```python
|
||||
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:**
|
||||
```python
|
||||
import seaborn as sns
|
||||
|
||||
okabe_ito_palette = ['#E69F00', '#56B4E9', '#009E73', '#F0E442',
|
||||
'#0072B2', '#D55E00', '#CC79A7']
|
||||
sns.set_palette(okabe_ito_palette)
|
||||
```
|
||||
|
||||
**Usage in Plotly:**
|
||||
```python
|
||||
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).
|
||||
|
||||
```python
|
||||
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):**
|
||||
```python
|
||||
tol_bright = ['#4477AA', '#EE6677', '#228833', '#CCBB44',
|
||||
'#66CCEE', '#AA3377', '#BBBBBB']
|
||||
```
|
||||
|
||||
**Muted Palette (up to 9 categories):**
|
||||
```python
|
||||
tol_muted = ['#332288', '#88CCEE', '#44AA99', '#117733',
|
||||
'#999933', '#DDCC77', '#CC6677', '#882255', '#AA4499']
|
||||
```
|
||||
|
||||
**High Contrast (3 categories only):**
|
||||
```python
|
||||
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
|
||||
```python
|
||||
plt.imshow(data, cmap='viridis')
|
||||
```
|
||||
|
||||
**Cividis:**
|
||||
- Optimized for colorblind viewers
|
||||
- Designed specifically for deuteranopia/protanopia
|
||||
```python
|
||||
plt.imshow(data, cmap='cividis')
|
||||
```
|
||||
|
||||
**Plasma, Inferno, Magma:**
|
||||
- Perceptually uniform alternatives to viridis
|
||||
- Good for different aesthetic preferences
|
||||
```python
|
||||
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):**
|
||||
```python
|
||||
plt.imshow(data, cmap='RdYlBu_r') # _r reverses: blue (low) to red (high)
|
||||
```
|
||||
|
||||
**PuOr (Purple-Orange):**
|
||||
- Excellent for colorblind viewers
|
||||
```python
|
||||
plt.imshow(data, cmap='PuOr')
|
||||
```
|
||||
|
||||
**BrBG (Brown-Blue-Green):**
|
||||
- Good colorblind accessibility
|
||||
```python
|
||||
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:**
|
||||
```python
|
||||
# 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:**
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
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
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# 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
|
||||
Reference in New Issue
Block a user