Scientific Visualization
by braselog
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 |
|---|---|---|
| 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
- Create figure directory:
manuscript/figures/figN/ - Save figure files:
figure.pdf,figure.png - Create caption:
caption.md - Reference in
manuscript/results.md - 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.
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.
Matplotlib
Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.
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.
Seaborn
Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.
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
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.
Query Writing
For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations
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.
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.
