EN

Scientific Data Visualization with Python: Publication-Ready Figures

Why This Matters

A well-designed figure communicates your results faster than any paragraph. Yet most researchers learn Matplotlib through copy-paste and trial-and-error. This guide gives you reusable templates for the four most common figure types in materials science.


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

# Global style for publication
plt.rcParams.update({
    "font.size": 10, "font.family": "sans-serif",
    "axes.labelsize": 11, "axes.titlesize": 12,
    "xtick.labelsize": 9, "ytick.labelsize": 9,
    "legend.fontsize": 9, "figure.dpi": 150,
    "savefig.dpi": 300, "savefig.bbox": "tight",
})

1. Multi-Panel Figure Template

The workhorse of any paper: 2x2 subplots comparing different conditions.


fig, axes = plt.subplots(2, 2, figsize=(10, 8))
axes = axes.flatten()

# Panel A: Stress-strain curves
axes[0].plot(strain, stress_control, "k-", label="Control")
axes[0].plot(strain, stress_treated, "r--", label="Treated")
axes[0].set_xlabel("Strain"); axes[0].set_ylabel("Stress (MPa)")
axes[0].legend(frameon=False)
axes[0].text(-0.1, 1.05, "A", transform=axes[0].transAxes, fontweight="bold", fontsize=12)

# Panel B: Box plot
df.boxplot(column="modulus", by="treatment", ax=axes[1])
axes[1].set_ylabel("Young's Modulus (GPa)")

# Panel C: Scatter with fit
axes[2].scatter(x, y, s=20, alpha=0.6)
axes[2].plot(x_fit, y_fit, "r-", linewidth=2)
axes[2].set_xlabel("Fiber Diameter (nm)"); axes[2].set_ylabel("Modulus (GPa)")

# Panel D: SEM image
axes[3].imshow(sem_image, cmap="gray")
axes[3].axis("off")

plt.tight_layout(pad=2)
plt.savefig("figure1.pdf", dpi=300)

2. Color Schemes

Avoid default Matplotlib colors. Use perceptually uniform or journal-specific palettes:


# Option A: Seaborn colorblind-friendly
sns.set_palette("colorblind")

# Option B: Custom scientific palette
colors = ["#1b9e77", "#d95f02", "#7570b3", "#e7298a"]

# Option C: Sequential (for heatmaps)
cmap = sns.color_palette("rocket_r", as_cmap=True)

3. Heatmaps for Matrix Data


fig, ax = plt.subplots(figsize=(6, 5))
im = ax.imshow(correlation_matrix, cmap="RdBu_r", vmin=-1, vmax=1)
cbar = plt.colorbar(im, ax=ax, shrink=0.8)
cbar.set_label("Pearson r")
ax.set_xticks(range(len(labels)))
ax.set_yticks(range(len(labels)))
ax.set_xticklabels(labels, rotation=45, ha="right")
ax.set_yticklabels(labels)

4. Export for Journals


# Nature/Science: 89 mm (single column) or 183 mm (double)
fig.set_size_inches(3.5, 3.0)  # Single column

# Export formats
plt.savefig("figure.pdf", dpi=300, bbox_inches="tight")  # Vector, editable
plt.savefig("figure.png", dpi=600)  # Raster, high-res
plt.savefig("figure.svg")  # Fully editable in Illustrator/Inkscape

5. Quick Reference

Chart TypeBest ForMatplotlib Function
----------------------------------------
Line plotStress-strain, time seriesplot()
ScatterCorrelation, PCAscatter()
Box plotGroup comparisonsboxplot()
Bar chartCategorical means + errorbar()
HeatmapCorrelation, 2D mapsimshow()
HistogramDistributionshist()
Violin plotDistribution comparisonviolinplot()

6. Tips for Reviewers

  • Never use red-green alone: 8% of males are colorblind
  • Label panels with bold letters: A, B, C in top-left corner
  • Report n values: Add sample size in captions
  • Show individual points: Don’t hide data behind bar charts
  • Use consistent fonts: Same family, size across all panels

References

  • Rougier, N.P. et al. (2014). Ten simple rules for better figures. PLoS Computational Biology, 10(9), e1003833.
  • Hunter, J.D. (2007). Matplotlib: A 2D graphics environment. Computing in Science & Engineering, 9(3), 90-95.

💬 Questions or Feedback?

This blog is actively maintained by a PhD researcher. Reach out on GitHub for collaborations or corrections.

View on GitHub