Scientific Visualization

by braselog

skill

Create publication-quality scientific figures with matplotlib, seaborn, and plotly. Includes multi-panel layouts, error bars, significance markers, colorblind-safe palettes, and journal-specific export (PDF/EPS/TIFF). Use when creating figures for manuscripts, presentations, or any research visualization.

Skill Details

Repository Files

1 file in this skill directory


name: scientific-visualization description: Create publication-quality scientific figures with matplotlib, seaborn, and plotly. Includes multi-panel layouts, error bars, significance markers, colorblind-safe palettes, and journal-specific export (PDF/EPS/TIFF). Use when creating figures for manuscripts, presentations, or any research visualization.

Scientific Visualization

Create publication-ready figures that are clear, accurate, and accessible.

When to Use

  • Creating plots or visualizations for manuscripts
  • Preparing figures for journal submission
  • Ensuring figures are colorblind-friendly and accessible
  • Making multi-panel figures with consistent styling
  • Exporting figures at correct resolution and format
  • Creating figures in manuscript/figures/figN/
  • During the ANALYSIS or WRITING phases

Quick Start: Publication Figure

import matplotlib.pyplot as plt
import numpy as np

# Publication settings
plt.rcParams.update({
    'font.family': 'sans-serif',
    'font.sans-serif': ['Arial', 'Helvetica'],
    'font.size': 8,
    'axes.labelsize': 9,
    'axes.titlesize': 10,
    'xtick.labelsize': 7,
    'ytick.labelsize': 7,
    'legend.fontsize': 7,
    'figure.dpi': 300,
    'savefig.dpi': 300,
    'savefig.bbox': 'tight',
})

# Create figure (single column = 3.5 inches / 89mm)
fig, ax = plt.subplots(figsize=(3.5, 2.5))

# Plot with colorblind-safe colors
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), color='#0072B2', label='sin(x)')
ax.plot(x, np.cos(x), color='#D55E00', label='cos(x)')

# Proper labeling with units
ax.set_xlabel('Time (s)')
ax.set_ylabel('Amplitude (mV)')
ax.legend(frameon=False)

# Clean style
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

# Save
fig.savefig('manuscript/figures/fig1/figure1.pdf')
fig.savefig('manuscript/figures/fig1/figure1.png', dpi=300)
plt.close()

Colorblind-Safe Palettes

Okabe-Ito Palette (Recommended)

# Best for categorical data - distinguishable by all color vision types
OKABE_ITO = [
    '#E69F00',  # Orange
    '#56B4E9',  # Sky Blue
    '#009E73',  # Bluish Green
    '#F0E442',  # Yellow
    '#0072B2',  # Blue
    '#D55E00',  # Vermillion
    '#CC79A7',  # Reddish Purple
    '#000000',  # Black
]

plt.rcParams['axes.prop_cycle'] = plt.cycler(color=OKABE_ITO)

For Continuous Data

# Use perceptually uniform colormaps
cmap = 'viridis'     # Default, good for most cases
cmap = 'plasma'      # High contrast
cmap = 'cividis'     # Colorblind-safe diverging

# AVOID: 'jet', 'rainbow', 'hsv' - these are NOT colorblind-safe

For Diverging Data

# Colorblind-safe diverging colormaps
cmap = 'RdBu_r'     # Red-Blue (reversed so blue = low)
cmap = 'PuOr'       # Purple-Orange
cmap = 'BrBG'       # Brown-Blue-Green

# Always center diverging maps at meaningful zero
sns.heatmap(data, cmap='RdBu_r', center=0)

Journal Figure Sizes

Common Widths (in inches)

Journal Single Column Double Column
Nature 3.5" (89mm) 7.2" (183mm)
Science 2.2" (55mm) 6.9" (175mm)
Cell 3.3" (85mm) 7.0" (178mm)
PLOS 5.2" 7.5"
Default 3.5" 7.0"

Resolution Requirements

Content Type Minimum DPI
Line art (graphs) 600-1200 (or vector)
Photographs 300-600
Combination 600

File Formats

Format Use For Notes
PDF Primary Vector, preserves quality
EPS Journals Vector, legacy support
TIFF Images Lossless raster
PNG Web/screen Lossless, smaller than TIFF
JPEG NEVER Lossy compression artifacts

Multi-Panel Figures

Using GridSpec

import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from string import ascii_uppercase

# Create figure with custom layout
fig = plt.figure(figsize=(7, 5))
gs = GridSpec(2, 3, figure=fig, hspace=0.4, wspace=0.4)

# Create panels
ax_a = fig.add_subplot(gs[0, 0])      # Top left
ax_b = fig.add_subplot(gs[0, 1:])     # Top right (spans 2 columns)
ax_c = fig.add_subplot(gs[1, 0])      # Bottom left
ax_d = fig.add_subplot(gs[1, 1])      # Bottom middle
ax_e = fig.add_subplot(gs[1, 2])      # Bottom right

# Add panel labels
axes = [ax_a, ax_b, ax_c, ax_d, ax_e]
for i, ax in enumerate(axes):
    ax.text(-0.15, 1.05, ascii_uppercase[i], transform=ax.transAxes,
            fontsize=12, fontweight='bold', va='top')
    
    # Example: clean up each axis
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

plt.savefig('manuscript/figures/fig1/figure1.pdf')

Using Subplots

fig, axes = plt.subplots(2, 2, figsize=(7, 6))
axes = axes.flatten()

for i, ax in enumerate(axes):
    ax.text(-0.1, 1.05, ascii_uppercase[i], transform=ax.transAxes,
            fontsize=12, fontweight='bold', va='top')

plt.tight_layout()

Common Plot Types

Bar Plot with Error Bars

import matplotlib.pyplot as plt
import numpy as np

groups = ['Control', 'Treatment A', 'Treatment B']
means = [10.2, 15.8, 18.3]
sems = [1.2, 1.5, 1.8]  # Standard error of mean
n = [20, 20, 20]

fig, ax = plt.subplots(figsize=(3.5, 3))

bars = ax.bar(groups, means, yerr=sems, capsize=4, 
              color=['#0072B2', '#E69F00', '#D55E00'],
              edgecolor='black', linewidth=0.5)

ax.set_ylabel('Response (AU)')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

# Add individual data points (transparency)
for i, (group, n_i) in enumerate(zip(groups, n)):
    x_jitter = np.random.normal(i, 0.05, n_i)
    y_data = np.random.normal(means[i], sems[i]*np.sqrt(n_i), n_i)
    ax.scatter(x_jitter, y_data, alpha=0.4, s=15, c='black')

plt.tight_layout()

Line Plot with Confidence Bands

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 50)
y = np.sin(x) + np.random.normal(0, 0.2, 50)
y_smooth = np.sin(x)
ci = 0.3  # Confidence interval width

fig, ax = plt.subplots(figsize=(4, 3))

# Confidence band
ax.fill_between(x, y_smooth - ci, y_smooth + ci, alpha=0.3, color='#0072B2')
# Line
ax.plot(x, y_smooth, color='#0072B2', linewidth=2)
# Data points
ax.scatter(x, y, s=20, alpha=0.5, color='#0072B2')

ax.set_xlabel('Time (s)')
ax.set_ylabel('Signal (AU)')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)

Box Plot with Significance Markers

import matplotlib.pyplot as plt
import seaborn as sns

fig, ax = plt.subplots(figsize=(4, 4))

# Box plot
sns.boxplot(data=df, x='group', y='value', palette='colorblind', ax=ax)

# Add individual points
sns.stripplot(data=df, x='group', y='value', color='black', 
              alpha=0.3, size=4, ax=ax)

# Add significance bar
y_max = df['value'].max()
ax.plot([0, 1], [y_max*1.1, y_max*1.1], 'k-', linewidth=1)
ax.text(0.5, y_max*1.12, '***', ha='center', fontsize=10)

ax.set_ylabel('Response (AU)')
sns.despine()

Heatmap with Proper Colorbar

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

# Correlation matrix example
fig, ax = plt.subplots(figsize=(5, 4))

# Mask upper triangle
mask = np.triu(np.ones_like(corr_matrix, dtype=bool))

sns.heatmap(corr_matrix, mask=mask, annot=True, fmt='.2f',
            cmap='RdBu_r', center=0, square=True,
            linewidths=0.5, cbar_kws={'shrink': 0.8},
            vmin=-1, vmax=1, ax=ax)

ax.set_title('Correlation Matrix')
plt.tight_layout()

Seaborn for Statistical Plots

import seaborn as sns

# Apply publication style
sns.set_theme(style='ticks', context='paper', font_scale=1.1)
sns.set_palette('colorblind')

# Violin plot with split
fig, ax = plt.subplots(figsize=(4, 3))
sns.violinplot(data=df, x='timepoint', y='expression',
               hue='treatment', split=True, inner='quartile', ax=ax)
ax.set_ylabel('Gene Expression (AU)')
sns.despine()

# Regression plot with CI
fig, ax = plt.subplots(figsize=(4, 3))
sns.regplot(data=df, x='predictor', y='outcome', 
            ci=95, scatter_kws={'alpha': 0.5}, ax=ax)
sns.despine()

Figure Export Workflow

For RA Projects

def save_figure(fig, fig_num, name):
    """Save figure in multiple formats following RA conventions."""
    import os
    
    # Create figure directory
    fig_dir = f'manuscript/figures/fig{fig_num}'
    os.makedirs(fig_dir, exist_ok=True)
    
    # Save in multiple formats
    fig.savefig(f'{fig_dir}/{name}.pdf', format='pdf', bbox_inches='tight')
    fig.savefig(f'{fig_dir}/{name}.png', format='png', dpi=300, bbox_inches='tight')
    fig.savefig(f'{fig_dir}/{name}.tiff', format='tiff', dpi=300, bbox_inches='tight')
    
    print(f"Saved: {fig_dir}/{name}.{{pdf,png,tiff}}")
    
# Usage
save_figure(fig, 1, 'treatment_comparison')

Caption Template

Create manuscript/figures/fig1/caption.md:

**Figure 1. Treatment comparison across experimental groups.**

(A) Response levels in control (n=20), Treatment A (n=20), and Treatment B (n=20) 
groups. Data shown as mean ± SEM with individual data points. ***p < 0.001, 
one-way ANOVA with Tukey's post-hoc test.

(B) Time course of response following treatment. Shaded regions indicate 95% 
confidence intervals. Treatment A (orange) shows significantly faster response 
than control (blue), p < 0.01.

Accessibility Checklist

  • Colorblind-safe palette (Okabe-Ito or viridis)
  • Works in grayscale (add patterns/markers if needed)
  • Font size ≥ 6pt at final print size
  • All axes labeled with units
  • Error bars defined in caption (SEM, SD, or CI)
  • No 3D effects or chartjunk
  • Legend readable and positioned appropriately
  • Resolution ≥ 300 DPI for raster, or vector format

Integration with RA Workflow

  1. Create figure directory: manuscript/figures/figN/
  2. Save figure files: figure.pdf, figure.png
  3. Create caption: caption.md
  4. Reference in manuscript/results.md
  5. Log activity in .research/logs/activity.md

Related Skills

Attack Tree Construction

Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.

skill

Grafana Dashboards

Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.

skill

Matplotlib

Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.

skill

Scientific Visualization

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.

skill

Seaborn

Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.

skill

Shap

Model interpretability and explainability using SHAP (SHapley Additive exPlanations). Use this skill when explaining machine learning model predictions, computing feature importance, generating SHAP plots (waterfall, beeswarm, bar, scatter, force, heatmap), debugging models, analyzing model bias or fairness, comparing models, or implementing explainable AI. Works with tree-based models (XGBoost, LightGBM, Random Forest), deep learning (TensorFlow, PyTorch), linear models, and any black-box model

skill

Pydeseq2

Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.

skill

Query Writing

For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations

skill

Pydeseq2

Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.

skill

Scientific Visualization

Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.

skill

Skill Information

Category:Skill
Last Updated:12/5/2025