BI

bio-data-visualization-color-palettes

Tools and principles for choosing data-safe, perceptually uniform color palettes for scientific visualization.

Install

mkdir -p .claude/skills/bio-data-visualization-color-palettes-fridrichmethod && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16052" && unzip -o skill.zip -d .claude/skills/bio-data-visualization-color-palettes-fridrichmethod && rm skill.zip

Installs to .claude/skills/bio-data-visualization-color-palettes-fridrichmethod

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Select colormaps and qualitative palettes for scientific figures using perceptual-uniformity, color-vision-deficiency safety, and luminance-monotonicity criteria. Covers Crameri scientific colormaps, viridis/cividis/magma, Okabe-Ito categorical, ColorBrewer, and the rainbow/jet critique. Use when choosing palettes for heatmaps, scatter, networks, or any encoding where color carries quantitative or categorical meaning.
421 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Beginner

Key capabilities

  • Select perceptually uniform colormaps
  • Choose color-vision-deficiency safe palettes
  • Ensure grayscale monotonicity
  • Match palettes to sequential data
  • Match palettes to diverging data

How it works

It guides the selection of colormaps and palettes based on perceptual uniformity, color-vision-deficiency safety, and luminance monotonicity, matching them to specific data types.

Inputs & outputs

You give it
data type (sequential, diverging, cyclic, categorical) and visualization goal
You get back
recommended colormap or qualitative palette (e.g., viridis, batlow, Okabe-Ito)

When to use bio-data-visualization-color-palettes

  • Choosing colors for heatmaps
  • Improving scatter plot readability
  • Ensuring scientific figure accessibility

About this skill

Version Compatibility

Reference examples tested with: viridis 0.6+, RColorBrewer 1.1+, scico 1.5+ (Crameri colormaps in R), khroma 1.12+ (Tol/Crameri palettes in R), matplotlib 3.8+, colorcet 3.0+, ggsci 3.0+, colorspace 2.1+.

Before using code patterns, verify installed versions match. If versions differ:

  • Python: pip show <package> then help(module.function) to check signatures
  • R: packageVersion('<pkg>') then ?function_name to verify parameters

If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt the example to match the actual API rather than retrying.

Color Palettes for Scientific Visualization

"Pick a color palette" -> Choose a colormap that (a) is perceptually uniform along the relevant data axis, (b) remains interpretable under common color-vision deficiencies, (c) prints correctly to grayscale, and (d) matches the data type — sequential, diverging, cyclic, or qualitative.

  • R: viridis::viridis, scico::scale_color_scico, khroma::color, RColorBrewer::brewer.pal
  • Python: matplotlib.colormaps, colorcet, seaborn.color_palette, cmcrameri.cm

The Three Modern Standards

  1. Perceptual uniformity -- equal data steps produce equal perceived color steps. viridis (van der Walt 2015), cividis (Nuñez 2018), and the Crameri family (batlow, roma, vik) are designed for this. Jet, rainbow, and red->green are not.

  2. Color vision deficiency safety -- ~6% of males have deuteranopia / protanopia (red-green deficiency). cividis was explicitly designed to be near-identical under normal and CVD viewing (Nuñez 2018 PLOS ONE 13:e0199239). The Okabe-Ito 8-color qualitative palette (popularized in Wong 2011 Nat Methods 8:441) is the CVD-safe categorical default.

  3. Grayscale monotonicity -- a perceptually-uniform sequential colormap has monotonically increasing luminance. Convert the figure to grayscale; if the order is still readable, the colormap is luminance-monotonic. This is the single most actionable test.

Palette Type by Data Type

Data typeUseAvoid
Sequential (expression, coverage, density)viridis, magma, cividis, batlow, liparijet, rainbow, hsv
Diverging (log fold change, z-score, signed correlation)vik, roma, RdBu, BrBG, PiYGjet, rainbow
Cyclic (phase, time-of-day, angle)romaO, vikO, twilightlinear sequential (wrap creates artifactual jump)
Categorical (≤8 groups)Okabe-Ito (Wong 2011), Tol bright, Dark2rainbow with N=20, Set1 if CVD matters
Categorical (9-20 groups)tab20, Paired, Polychrometoo-many categorical hues -- consider faceting
Categorical (>20)None -- reconsider designMore colors will not help

The Crameri Scientific Colormaps

Crameri 2020 Nat Commun 11:5444 documented the prevalence of misleading palettes (rainbow, red-green) across published science and released a family of perceptually-uniform CVD-safe colormaps via Zenodo (doi:10.5281/zenodo.8409685). Key entries:

Crameri nameTypeUse case
batlowsequentialDefault jet replacement; runs through dark-blue -> ochre -> light-yellow
liparisequentialHigher-saturation alternative; better for projection
vikdivergingBlue -> white -> red equivalent, perceptually uniform
romadivergingSlightly warmer than vik
bamdivergingBrown -> white -> green
romaOcyclicPhase, time-of-day, angle data
vikOcyclicDiverging cyclic
library(scico)
# Sequential
ggplot(df, aes(x, y, fill = value)) + geom_tile() +
    scale_fill_scico(palette = 'batlow')
# Diverging
ggplot(df, aes(x, y, fill = lfc)) + geom_tile() +
    scale_fill_scico(palette = 'vik', midpoint = 0)
from cmcrameri import cm
import matplotlib.pyplot as plt
plt.imshow(data, cmap=cm.batlow)         # sequential
plt.imshow(data, cmap=cm.vik, vmin=-vmax, vmax=vmax)   # diverging, symmetric

viridis Family (matplotlib default since 3.0)

library(viridis)
scale_color_viridis_c(option = 'viridis')   # default: dark blue -> yellow
scale_color_viridis_c(option = 'magma')     # black -> red -> yellow
scale_color_viridis_c(option = 'inferno')   # black -> purple -> yellow
scale_color_viridis_c(option = 'plasma')    # purple -> pink -> yellow
scale_color_viridis_c(option = 'cividis')   # CVD-optimized
scale_color_viridis_c(option = 'turbo')     # jet-like but perceptually uniform
plt.imshow(data, cmap='viridis')   # 'magma', 'inferno', 'plasma', 'cividis', 'turbo'

cividis is the only viridis-family colormap optimized for CVD. Use it for any figure intended to remain interpretable under deuteranopia/protanopia.

Okabe-Ito Categorical Palette (Wong 2011)

The 8-color CVD-safe categorical palette. Memorize the hexes:

okabe_ito <- c(
    '#E69F00',  # orange
    '#56B4E9',  # sky blue
    '#009E73',  # bluish green
    '#F0E442',  # yellow
    '#0072B2',  # blue
    '#D55E00',  # vermilion
    '#CC79A7',  # reddish purple
    '#000000'   # black
)
scale_color_manual(values = okabe_ito)

Available as palette.colors(8, 'Okabe-Ito') in R 4.0+, scale_color_manual(values = palette.colors(8, 'Okabe-Ito')). In matplotlib, colorblind style or manual hex list.

For DE plots, the canonical assignment is Up = #D55E00 (vermilion), Down = #0072B2 (blue), NS = #999999 (grey).

ColorBrewer (Harrower & Brewer 2003)

library(RColorBrewer)
display.brewer.all()                    # interactive palette browser
display.brewer.all(colorblindFriendly = TRUE)   # CVD-safe subset only
brewer.pal(n = 8, name = 'Dark2')       # qualitative
brewer.pal(n = 9, name = 'YlOrRd')      # sequential
brewer.pal(n = 11, name = 'RdBu')       # diverging

ColorBrewer's CVD-safe sequential and diverging palettes are publication-defaults. For qualitative beyond 8 colors, switch to Tol/Polychrome — ColorBrewer qualitative tops out at 12 (Set3).

Scientific Journal Brand Palettes

library(ggsci)
scale_color_npg()       # Nature Publishing Group
scale_color_aaas()      # Science (AAAS)
scale_color_lancet()    # Lancet
scale_color_jama()      # JAMA
scale_color_jco()       # JCO
scale_color_nejm()      # NEJM

These are CVD-imperfect — use journal palettes for stylistic compliance, not for accessibility. Verify by colorblindness simulation (below).

CVD Simulation -- The Mandatory Check

library(colorspace)
# Simulate deuteranopia / protanopia on a palette
cvd_emulator(palette, type = 'deutan')
cvd_emulator(palette, type = 'protan')
cvd_emulator(palette, type = 'tritan')

# Visual side-by-side
demoplot(palette, type = 'heatmap')
# colorspacious provides CVD simulation
from colorspacious import cspace_converter
# or use a CVD-safe palette by construction (cividis, Okabe-Ito, Crameri)

If a palette is unreadable under deutan simulation, do not use it for accessible figures. Period.

Grayscale Monotonicity Test

library(scales)
show_col(viridis(10))           # full color
show_col(grey(seq(0, 1, length = 10)))   # equivalent grayscale gradient

In practice: save the figure as PNG, open in an image editor, desaturate. If the data order is still readable, the colormap is luminance-monotonic. If it shows arbitrary "rings" or "bands," the colormap is non-monotonic — fix before submitting.

Rainbow / jet fails this test catastrophically. viridis and cividis pass.

Diverging Palette Setup (LFC, z-score)

library(circlize)
col_fun <- colorRamp2(c(-2, 0, 2), c('#0072B2', 'white', '#D55E00'))
# Symmetric around 0; ALWAYS use symmetric bounds for signed data
import matplotlib.pyplot as plt
plt.imshow(data, cmap='RdBu_r', vmin=-2, vmax=2)   # symmetric
# do NOT use vmin=data.min(), vmax=data.max() for diverging data

The most common diverging-palette error is asymmetric bounds (vmin=min, vmax=max) which mis-aligns zero with the white midpoint.

Custom Palette Construction

# Discrete categorical
my_palette <- c('Control' = '#0072B2', 'Treatment' = '#D55E00', 'Vehicle' = '#009E73')
scale_color_manual(values = my_palette)

# Continuous gradient between custom colors
colorRampPalette(c('#0072B2', 'white', '#D55E00'))(100)
from matplotlib.colors import LinearSegmentedColormap
cmap = LinearSegmentedColormap.from_list('cvd_div', ['#0072B2', '#FFFFFF', '#D55E00'])

When building a custom diverging palette: pick endpoints with similar luminance (so neither side dominates), pass through pure white at the midpoint (NOT light gray), and verify with the grayscale test.

Common Failure Modes

Asymmetric bounds on diverging data

Trigger: vmin=data.min(), vmax=data.max() on signed data with skewed distribution.

Mechanism: Zero no longer maps to the midpoint (white) of the diverging palette.

Symptom: Half the cells visually look "below zero" but are actually positive; reviewer confusion.

Fix: vmax = max(abs(data.min()), abs(data.max())); then vmin = -vmax. Or pre-clip data to a fixed range.

Categorical palette with too many colors

Trigger: 15+ groups all on one colormap.

Mechanism: Human color discrimination saturates around 8-10 distinct hues.

Symptom: Groups look identical; legend has no information value.

Fix: Facet by category, or aggregate small groups into "Other," or use a categorical+marker-shape combination.

Rainbow / jet still in use

Trigger: Default colormaps in older matplotlib (<2.0), MATLAB-derived code, or colorRampPalette(rainbow(...)).

Mechanism: Rainbow has non-monotonic luminance and includes a perceptual "yellow band" that creates artifactual boundaries.

Symptom: Figures show banding that doesn't exist in the data; CVD viewers cannot interpret.

Fix: Migrate to viridis (sequential) or vik/roma (diverging). For nostalgic jet-like appearance with perceptual properties, use `


Content truncated.

When not to use it

  • When using jet, rainbow, or hsv colormaps for sequential data
  • When using linear sequential colormaps for cyclic data
  • When using too many categorical hues for more than 20 groups

Limitations

  • Reference examples tested with specific package versions (e.g., viridis 0.6+, RColorBrewer 1.1+)
  • Python: pip show <package> then help(module.function) to check signatures
  • R: packageVersion('<pkg>') then ?function_name to verify parameters

How it compares

This skill provides a systematic, evidence-based approach to color selection for scientific figures, avoiding common pitfalls of misleading palettes like rainbow or jet.

Compared to similar skills

bio-data-visualization-color-palettes side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
bio-data-visualization-color-palettes (this skill)02moNo flagsBeginner
openalex-database488moReviewIntermediate
scientific-visualization268moReviewIntermediate
matplotlib01moReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

More by FridrichMethod

View all by FridrichMethod

shap-model-explainability

FridrichMethod

Model interpretability via SHAP (Shapley values from game theory). Covers explainer choice (Tree, Deep, Linear, Kernel, Gradient, Permutation), feature attribution, and plots (waterfall, beeswarm, bar, scatter, force, heatmap). Use to explain ML predictions, rank features, debug models, audit fairne

00

bio-genome-intervals-coverage-analysis

FridrichMethod

Computes and interprets sequencing read depth and coverage over a genome, windows, or target regions with mosdepth (windowed depth, cumulative distribution, --quantize callable BEDs), bedtools genomecov/coverage (bedGraph tracks, per-target stats), samtools depth/coverage (per-base depth, per-contig

00

openalex-database

FridrichMethod

Query OpenAlex REST API for 250M+ scholarly works, authors, institutions, journals, concepts. Search by keyword, author, DOI, ORCID, or ID; filter by year, OA, citations, field; retrieve citations, references, author disambiguation. Free, no auth. For PubMed use pubmed-database; preprints use biorxi

00

bio-alignment-msa-parsing

FridrichMethod

Parse and analyze multiple sequence alignments using Biopython. Extract sequences, identify conserved regions, analyze gaps, work with annotations, and manipulate alignment data for downstream analysis. Use when parsing or manipulating multiple sequence alignments.

00

bio-population-genetics-rare-variant-association

FridrichMethod

Gene and region-based rare-variant aggregation - burden/collapsing, SKAT, SKAT-O, ACAT-V/ACAT-O, annotation-weighted STAAR - with regenie (--vc-tests), SAIGE-GENE+, and the SKAT R package. Single-variant tests are powerless at low minor allele count, so rare variants are aggregated across a gene or

00

bio-workflows-liquid-biopsy-pipeline

FridrichMethod

Orchestrates the cell-free DNA / liquid-biopsy pipeline from plasma sequencing to tumor monitoring, forking tumor-naive (screening) vs tumor-informed (MRD), and chaining pre-analytic QC, UMI/duplex error-suppression (fgbio), fragment QC, ichorCNA tumor fraction (sWGS) or VarDict low-VAF calling (pan

00

You might also like

openalex-database

davila7

Query and analyze scholarly literature using the OpenAlex database. This skill should be used when searching for academic papers, analyzing research trends, finding works by authors or institutions, tracking citations, discovering open access publications, or conducting bibliometric analysis across 240M+ scholarly works. Use for literature searches, research output analysis, citation analysis, and academic database queries.

48202

scientific-visualization

davila7

Create publication figures with matplotlib/seaborn/plotly. Multi-panel layouts, error bars, significance markers, colorblind-safe, export PDF/EPS/TIFF, for journal-ready scientific plots.

2661

matplotlib

liq22

Implementation skill for low-level plotting with matplotlib (Python). Use for fine-grained control over plot elements, novel plot types (3D surfaces, custom projections), subplots/mosaics, rcParams styling, or PNG/PDF/SVG export. Do not use for figure planning — defer to scientific-visualization; th

00

visualization

NNNightglow

构建并路由 A 股可视化任务到 `utils/visualizers` 与 `utils/visualizer_manager.py` 的正确图表管线。用于用户请求个股、指数、板块、市场情绪或模型结果图表,且需要判断所需输入字段、方法选择与输出格式(嵌入式 HTML 或 ECharts 选项)。

00

bio-data-visualization-color-palettes

sulfierry

Select and apply colorblind-friendly palettes for scientific figures using viridis, RColorBrewer, and custom color schemes. Use when selecting colorblind-friendly palettes for figures.

00

beamer-ppt

zhouziyue233

Create Beamer-style academic PPTX presentations using python-pptx. Produces publication-quality .pptx files with navy-blue Metropolis theme (16:9, frame title bars, progress bar) for conference talks, job market presentations, and seminar slides. Called by /present command.

00

Search skills

Search the agent skills registry