S

Scientific Visualization System

Comprehensive skill designed for create, publication, figures, matplotlib. Includes structured workflows, validation checks, and reusable patterns for scientific.

SkillClipticsscientificv1.0.0MIT
0 views0 copies

Scientific Visualization System

Create publication-quality scientific figures with multi-panel layouts, statistical annotations, colorblind-safe palettes, and journal-ready export using matplotlib, seaborn, and plotly. This skill covers figure composition, axis customization, 3D visualization, animated plots, and automated figure generation pipelines.

When to Use This Skill

Choose Scientific Visualization System when you need to:

  • Create multi-panel figures with shared axes and consistent styling for journal submission
  • Build publication-quality plots with proper error bars, significance markers, and annotations
  • Generate colorblind-safe, grayscale-compatible visualizations
  • Automate figure generation pipelines for reproducible research outputs

Consider alternatives when:

  • You need interactive web dashboards (use Plotly Dash or Streamlit)
  • You need geographic/spatial visualization (use GeoPandas or Folium)
  • You need presentation-specific slides with figures (use Scientific Slides Elite)

Quick Start

pip install matplotlib seaborn numpy scipy
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import seaborn as sns import numpy as np # Set publication style globally plt.rcParams.update({ 'font.family': 'sans-serif', 'font.sans-serif': ['Arial'], 'font.size': 10, 'axes.linewidth': 1.0, 'xtick.major.width': 1.0, 'ytick.major.width': 1.0, 'figure.dpi': 150, 'savefig.dpi': 300, 'savefig.bbox': 'tight', 'savefig.pad_inches': 0.05, }) # Create a multi-panel figure fig = plt.figure(figsize=(7, 6)) # Single column width gs = gridspec.GridSpec(2, 2, hspace=0.35, wspace=0.35) # Panel A: Bar plot with error bars ax1 = fig.add_subplot(gs[0, 0]) conditions = ['Control', 'Treatment A', 'Treatment B'] means = [12.3, 18.7, 15.2] sems = [1.1, 1.8, 1.3] bars = ax1.bar(conditions, means, yerr=sems, capsize=4, color=['#4C72B0', '#DD8452', '#55A868'], edgecolor='black', linewidth=0.5) ax1.set_ylabel('Expression Level (AU)') ax1.set_title('Gene Expression', fontweight='bold', fontsize=11) # Panel B: Scatter with regression ax2 = fig.add_subplot(gs[0, 1]) np.random.seed(42) x = np.random.randn(50) * 2 + 5 y = 1.5 * x + np.random.randn(50) * 2 + 3 ax2.scatter(x, y, s=30, alpha=0.7, color='#4C72B0', edgecolor='white', linewidth=0.5) z = np.polyfit(x, y, 1) xline = np.linspace(x.min(), x.max(), 100) ax2.plot(xline, np.polyval(z, xline), 'r-', linewidth=1.5) ax2.set_xlabel('Variable X') ax2.set_ylabel('Variable Y') ax2.set_title('Correlation', fontweight='bold', fontsize=11) # Panel C: Heatmap ax3 = fig.add_subplot(gs[1, 0]) data = np.random.randn(6, 6) sns.heatmap(data, ax=ax3, cmap='RdBu_r', center=0, square=True, linewidths=0.5, cbar_kws={'shrink': 0.8}) ax3.set_title('Expression Matrix', fontweight='bold', fontsize=11) # Panel D: Box plot ax4 = fig.add_subplot(gs[1, 1]) box_data = [np.random.randn(30) + i for i in range(4)] bp = ax4.boxplot(box_data, patch_artist=True, widths=0.6, medianprops=dict(color='black', linewidth=1.5)) colors_box = ['#4C72B0', '#DD8452', '#55A868', '#C44E52'] for patch, color in zip(bp['boxes'], colors_box): patch.set_facecolor(color) patch.set_alpha(0.7) ax4.set_xticklabels(['WT', 'KO1', 'KO2', 'Rescue']) ax4.set_ylabel('Measurement') ax4.set_title('Distribution', fontweight='bold', fontsize=11) # Add panel labels for ax, label in zip([ax1, ax2, ax3, ax4], ['A', 'B', 'C', 'D']): ax.text(-0.15, 1.05, label, transform=ax.transAxes, fontsize=14, fontweight='bold', va='bottom') fig.savefig('figure1.pdf', format='pdf') fig.savefig('figure1.tiff', format='tiff', dpi=300) print("Multi-panel figure saved as PDF and TIFF")

Core Concepts

Plot Types for Scientific Data

Plot TypeBest Formatplotlib/seaborn Function
Bar + error barsGroup comparisonsax.bar() + yerr
Box/violinDistribution comparisonsns.boxplot(), sns.violinplot()
Scatter + regressionCorrelationsax.scatter() + np.polyfit()
HeatmapMatrix data, expressionsns.heatmap()
Line + confidence bandTime series, dose-responseax.plot() + ax.fill_between()
Kaplan-MeierSurvival analysislifelines + matplotlib
Volcano plotDifferential expressionCustom scatter with thresholds
PCA/UMAPDimensionality reductionScatter with cluster coloring

Statistical Annotation System

import matplotlib.pyplot as plt import numpy as np from scipy import stats def add_significance_bracket(ax, x1, x2, y, p_value, height=0.02): """Add a significance bracket between two bars.""" if p_value < 0.001: sig_text = '***' elif p_value < 0.01: sig_text = '**' elif p_value < 0.05: sig_text = '*' else: sig_text = 'ns' y_range = ax.get_ylim()[1] - ax.get_ylim()[0] bar_height = y_range * height ax.plot([x1, x1, x2, x2], [y, y + bar_height, y + bar_height, y], color='black', linewidth=1.0) ax.text((x1 + x2) / 2, y + bar_height, sig_text, ha='center', va='bottom', fontsize=11, fontweight='bold') # Example with t-test annotations fig, ax = plt.subplots(figsize=(4, 4)) groups = ['Control', 'Drug A', 'Drug B'] data = [np.random.randn(20) + m for m in [5, 7.5, 6.2]] means = [d.mean() for d in data] sems = [d.std() / np.sqrt(len(d)) for d in data] ax.bar(range(3), means, yerr=sems, capsize=4, color=['#4C72B0', '#DD8452', '#55A868'], edgecolor='black', linewidth=0.5) ax.set_xticks(range(3)) ax.set_xticklabels(groups) ax.set_ylabel('Response (AU)') # Add significance brackets _, p_val = stats.ttest_ind(data[0], data[1]) add_significance_bracket(ax, 0, 1, max(means) + max(sems) + 0.5, p_val) fig.tight_layout() fig.savefig('annotated_bar.pdf')

Configuration

ParameterDescriptionDefault
figure.figsizeFigure dimensions in inches (width, height)(7, 5)
savefig.dpiOutput resolution for raster formats300
font.sizeBase font size in points10
font.familyFont family"sans-serif"
axes.linewidthAxis border thickness1.0
figure.facecolorBackground color"white"
savefig.formatDefault save format"pdf"
image.cmapDefault colormap"viridis"

Best Practices

  1. Use vector formats for line art, raster for complex images — Save line plots, bar charts, and schematics as PDF or SVG for infinite scalability. Save heatmaps, microscopy overlays, and photos as TIFF at 300 DPI. Most journals accept both and many require specific formats per figure type.

  2. Apply colorblind-safe palettes by default — About 8% of men have color vision deficiency. Use palettes like colorblind from seaborn, or manually select distinguishable colors (blue/orange rather than red/green). Test with a colorblindness simulator before submission.

  3. Size figures to their final print dimensions — Create figures at the exact width the journal specifies (typically 3.5" for single column, 7" for double column). This ensures fonts are readable at the printed size. Never rely on the journal to scale your figure — text will be too small or too large.

  4. Use GridSpec for complex multi-panel layoutsmatplotlib.gridspec.GridSpec gives precise control over panel sizes and spacing. Use hspace and wspace for gaps, and height_ratios/width_ratios for non-uniform panels. Add bold uppercase labels (A, B, C) in the top-left of each panel.

  5. Separate data processing from visualization — Load and process data in one script, save intermediates, then create figures in a separate script. This lets you regenerate figures without re-running expensive computations and makes it easy to tweak aesthetics without touching the analysis pipeline.

Common Issues

Fonts are substituted or missing in PDF output — matplotlib embeds fonts in PDFs, but some fonts aren't available on all systems. Use plt.rcParams['pdf.fonttype'] = 42 to embed fonts as TrueType (not Type 3), which journals and reviewers can open correctly. Stick to common fonts like Arial or Helvetica.

Axis labels or titles are cut off in saved figures — Use bbox_inches='tight' in savefig() to auto-expand the bounding box. Also set pad_inches=0.05 for a small margin. For very tight layouts, manually adjust subplot parameters with fig.subplots_adjust() or switch to constrained_layout=True.

Colorbar size doesn't match the plot height — Seaborn and matplotlib colorbars default to the full figure height, which looks wrong in multi-panel layouts. Use cbar_kws={'shrink': 0.8} in seaborn heatmaps, or create a dedicated colorbar axis with fig.colorbar(im, cax=cbar_ax) and control its size via GridSpec.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates