Matplotlib Scientific Plotting logo

Matplotlib Scientific Plotting

Community
jaechang-hits
matplotlib-scientific-plotting

Low-level Python plotting for scientific figures: publication-quality line, scatter, bar, heatmap, contour, 3D; multi-panel layouts; fine control of every element. PNG/PDF/SVG export. Use seaborn for quick stats, plotly for interactive.

Overview

Publisherjaechang-hits
RepositorySciAgent-Skills
Skill namematplotlib-scientific-plotting
Stars
381
Forks
45
Bundled files
Instructions only
LicensePSF-based
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by jaechang-hits on GitHub. Read the source before you install it.

Installation

Install the Matplotlib Scientific Plotting AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/data-visualization/matplotlib-scientific-plotting
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git /tmp/SciAgent-Skills
mkdir -p .claude/skills
cp -r /tmp/SciAgent-Skills/skills/data-visualization/matplotlib-scientific-plotting .claude/skills/matplotlib-scientific-plotting
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Matplotlib Scientific Plotting in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Matplotlib Scientific Plotting on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Matplotlib Scientific Plotting is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

matplotlib

Overview

Matplotlib is Python's foundational visualization library for creating static, animated, and interactive plots. It provides both a MATLAB-style pyplot interface and an object-oriented API for full control over figures, axes, and artists. Essential for generating publication-quality scientific figures.

When to Use

  • Creating publication-quality plots with precise control over every element (fonts, ticks, colors, spacing)
  • Building multi-panel figures with complex subplot layouts for papers
  • Generating standard scientific plot types: line, scatter, bar, histogram, heatmap, box, violin, contour
  • Exporting figures to vector formats (PDF, SVG) for journal submission
  • Creating 3D surface, scatter, or wireframe plots
  • Customizing colormaps and color schemes for accessibility (colorblind-friendly)
  • Integrating plots with NumPy arrays and pandas DataFrames
  • For quick statistical visualizations (distributions, regressions), use seaborn instead
  • For interactive/web-based plots with hover and zoom, use plotly instead

Prerequisites

  • Python packages: matplotlib, numpy
  • Optional: pandas (for DataFrame plotting), seaborn (for style presets)
  • Environment: Works in scripts, Jupyter notebooks (%matplotlib inline), and GUI apps
bash
pip install matplotlib numpy

Quick Start

python
import matplotlib.pyplot as plt
import numpy as np

# Publication-ready figure template: set size, plot, label, save as PDF
fig, ax = plt.subplots(figsize=(6, 4))  # single-column journal width ≈ 6 cm → set here in inches

x = np.linspace(0, 2 * np.pi, 200)
ax.plot(x, np.sin(x), color="steelblue", lw=1.5, label="sin(x)")
ax.plot(x, np.cos(x), color="coral",    lw=1.5, label="cos(x)", linestyle="--")

ax.set_xlabel("x (radians)")
ax.set_ylabel("Amplitude")
ax.set_title("Sine and Cosine Waves")
ax.legend(frameon=False)
ax.spines[["top", "right"]].set_visible(False)  # clean axis style

plt.tight_layout()
plt.savefig("quickstart.pdf", bbox_inches="tight", dpi=300)
print("Saved quickstart.pdf")

Core API

Module 1: Figure and Axes Creation

The fundamental objects: Figure (canvas) and Axes (plotting area).

python
import matplotlib.pyplot as plt
import numpy as np

# Single plot (recommended: OO interface)
fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 2 * np.pi, 100)
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
ax.set_xlabel("x"); ax.set_ylabel("y")
ax.set_title("Trigonometric Functions")
ax.legend(); ax.grid(True, alpha=0.3)
plt.savefig("basic_plot.png", dpi=300, bbox_inches="tight")
print("Saved basic_plot.png")
python
# Multi-panel subplots
fig, axes = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)
axes[0, 0].plot(x, np.sin(x)); axes[0, 0].set_title("sin(x)")
axes[0, 1].scatter(x[::5], np.cos(x[::5])); axes[0, 1].set_title("cos(x)")
axes[1, 0].bar(["A", "B", "C"], [3, 7, 5]); axes[1, 0].set_title("Bar")
axes[1, 1].hist(np.random.randn(500), bins=30); axes[1, 1].set_title("Histogram")
plt.savefig("subplots.png", dpi=300, bbox_inches="tight")
print("Saved subplots.png with 4 panels")

Module 2: Plot Types

Standard scientific chart types.

python
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(2, 3, figsize=(15, 9), constrained_layout=True)

# Line plot — trends over time
x = np.linspace(0, 10, 50)
axes[0, 0].plot(x, np.exp(-x/3) * np.sin(x), "b-", linewidth=2)
axes[0, 0].set_title("Line Plot")

# Scatter plot — correlations
np.random.seed(42)
axes[0, 1].scatter(np.random.randn(100), np.random.randn(100), alpha=0.6, c=np.random.rand(100), cmap="viridis")
axes[0, 1].set_title("Scatter Plot")

# Bar chart — categorical comparisons
categories = ["Gene A", "Gene B", "Gene C", "Gene D"]
axes[0, 2].bar(categories, [4.2, 7.1, 3.5, 6.8], color="steelblue", edgecolor="black")
axes[0, 2].set_title("Bar Chart")

# Histogram — distributions
axes[1, 0].hist(np.random.randn(1000), bins=40, edgecolor="black", alpha=0.7)
axes[1, 0].set_title("Histogram")

# Box plot — statistical distributions
data = [np.random.randn(50) + i for i in range(4)]
axes[1, 1].boxplot(data, labels=["Ctrl", "Drug A", "Drug B", "Drug C"])
axes[1, 1].set_title("Box Plot")

# Heatmap — matrix data
matrix = np.random.rand(8, 8)
im = axes[1, 2].imshow(matrix, cmap="coolwarm", aspect="auto")
plt.colorbar(im, ax=axes[1, 2])
axes[1, 2].set_title("Heatmap")

plt.savefig("plot_types.png", dpi=300, bbox_inches="tight")
print("Saved 6 plot types to plot_types.png")

Module 3: Styling and Customization

Colors, fonts, styles, annotations.

python
import matplotlib.pyplot as plt
import numpy as np

# Use style sheets
plt.style.use("seaborn-v0_8-whitegrid")

# Custom rcParams for publication
plt.rcParams.update({
    "font.size": 12, "axes.labelsize": 14,
    "axes.titlesize": 16, "xtick.labelsize": 10,
    "ytick.labelsize": 10, "legend.fontsize": 11,
})

fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 5, 100)
ax.plot(x, np.exp(-x), "r--", linewidth=2, label="Exponential decay")
ax.fill_between(x, np.exp(-x) - 0.1, np.exp(-x) + 0.1, alpha=0.2, color="red")

# Annotations
ax.annotate("Half-life", xy=(0.693, 0.5), xytext=(2, 0.7),
            arrowprops=dict(arrowstyle="->", color="black"),
            fontsize=12, fontweight="bold")
ax.set_xlabel("Time (s)"); ax.set_ylabel("Signal")
ax.legend()
plt.savefig("styled_plot.png", dpi=300, bbox_inches="tight")
print("Saved styled_plot.png")

Module 4: Advanced Layouts

Mosaic layouts, GridSpec, insets.

python
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np

# Mosaic layout — named axes
fig, axes = plt.subplot_mosaic(
    [["main", "right"], ["main", "bottom_right"]],
    figsize=(10, 7), constrained_layout=True,
    gridspec_kw={"width_ratios": [2, 1]}
)
x = np.linspace(0, 10, 200)
axes["main"].plot(x, np.sin(x) * np.exp(-x/5), "b-", linewidth=2)
axes["main"].set_title("Main Panel")
axes["right"].hist(np.random.randn(300), bins=20, orientation="horizontal")
axes["right"].set_title("Distribution")
axes["bottom_right"].bar(["A", "B"], [3, 5])
axes["bottom_right"].set_title("Summary")
plt.savefig("mosaic_layout.png", dpi=300, bbox_inches="tight")
print("Saved mosaic_layout.png")

Module 5: 3D Visualization

Surface, scatter, and wireframe plots.

python
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection="3d")

# Surface plot
u = np.linspace(0, 2 * np.pi, 50)
v = np.linspace(0, np.pi, 50)
X = np.outer(np.cos(u), np.sin(v))
Y = np.outer(np.sin(u), np.sin(v))
Z = np.outer(np.ones_like(u), np.cos(v))

ax.plot_surface(X, Y, Z, cmap="viridis", alpha=0.8)
ax.set_xlabel("X"); ax.set_ylabel("Y"); ax.set_zlabel("Z")
ax.set_title("3D Surface Plot")
plt.savefig("surface_3d.png", dpi=300, bbox_inches="tight")
print("Saved surface_3d.png")

Module 6: Export and Saving

Output to various formats with publication settings.

python
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(6, 4))
ax.plot([1, 2, 3], [1, 4, 9], "ko-")
ax.set_title("Export Example")

# High-res PNG for presentations
fig.savefig("figure.png", dpi=300, bbox_inches="tight", facecolor="white")

# Vector PDF for journal submission
fig.savefig("figure.pdf", bbox_inches="tight")

# SVG for web
fig.savefig("figure.svg", bbox_inches="tight")

# Transparent background
fig.savefig("figure_transparent.png", dpi=300, bbox_inches="tight", transparent=True)

plt.close(fig)  # Free memory
print("Exported to PNG, PDF, SVG, and transparent PNG")

Common Workflows

Workflow 1: Multi-Panel Figure for Publication

Goal: Create a 4-panel figure combining different plot types for a paper.

python
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)
fig, axes = plt.subplots(2, 2, figsize=(10, 8), constrained_layout=True)

# Panel A: Time series
t = np.linspace(0, 24, 100)
axes[0, 0].plot(t, 50 + 10 * np.sin(t * np.pi / 12), "b-", linewidth=2)
axes[0, 0].set_xlabel("Time (h)"); axes[0, 0].set_ylabel("Expression")
axes[0, 0].set_title("A", loc="left", fontweight="bold")

# Panel B: Volcano plot
fc = np.random.randn(500)
pval = -np.log10(np.random.uniform(0.0001, 1, 500))
colors = ["red" if abs(f) > 1 and p > 2 else "grey" for f, p in zip(fc, pval)]
axes[0, 1].scatter(fc, pval, c=colors, s=10, alpha=0.7)
axes[0, 1].axhline(2, ls="--", color="black", alpha=0.5)
axes[0, 1].set_xlabel("log₂ FC"); axes[0, 1].set_ylabel("-log₁₀ p-value")
axes[0, 1].set_title("B", loc="left", fontweight="bold")

# Panel C: Bar chart with error bars
means = [3.2, 5.1, 4.7, 6.3]
sems = [0.4, 0.6, 0.3, 0.5]
axes[1, 0].bar(["Ctrl", "Drug A", "Drug B", "Combo"], means, yerr=sems,
               capsize=5, color="steelblue", edgecolor="black")
axes[1, 0].set_ylabel("Response"); axes[1, 0].set_title("C", loc="left", fontweight="bold")

# Panel D: Heatmap
data = np.random.randn(6, 4)
im = axes[1, 1].imshow(data, cmap="RdBu_r", aspect="auto")
plt.colorbar(im, ax=axes[1, 1])
axes[1, 1].set_title("D", loc="left", fontweight="bold")

fig.savefig("publication_figure.pdf", bbox_inches="tight")
print("Saved publication_figure.pdf (4 panels)")

Workflow 2: Statistical Comparison Plot

Goal: Bar chart with individual data points and significance annotations.

python
import matplotlib.pyplot as plt
import numpy as np

np.random.seed(42)
groups = {"Control": np.random.normal(5, 1.2, 20),
          "Treatment A": np.random.normal(7, 1.5, 20),
          "Treatment B": np.random.normal(6, 1.0, 20)}

fig, ax = plt.subplots(figsize=(6, 5))
positions = range(len(groups))
for i, (name, data) in enumerate(groups.items()):
    ax.bar(i, np.mean(data), yerr=np.std(data)/np.sqrt(len(data)),
           capsize=5, color=["#4C72B0", "#DD8452", "#55A868"][i],
           edgecolor="black", alpha=0.8, width=0.6)
    # Overlay individual data points
    ax.scatter(np.full_like(data, i) + np.random.uniform(-0.15, 0.15, len(data)),
               data, color="black", s=15, alpha=0.5, zorder=5)

ax.set_xticks(positions); ax.set_xticklabels(groups.keys())
ax.set_ylabel("Measurement")

# Add significance bracket
y_max = max(max(d) for d in groups.values()) + 1
ax.plot([0, 0, 1, 1], [y_max, y_max + 0.2, y_max + 0.2, y_max], "k-", linewidth=1)
ax.text(0.5, y_max + 0.3, "**", ha="center", fontsize=14)

fig.savefig("comparison_plot.png", dpi=300, bbox_inches="tight")
print("Saved comparison_plot.png")

Key Parameters

ParameterModuleDefaultRange / OptionsEffect
figsizeFigure creation(6.4, 4.8)(w, h) in inchesFigure dimensions
dpisavefig10072-600Resolution: 300 for print, 150 for web
bbox_inchessavefigNone"tight", NoneCrop whitespace around figure
constrained_layoutsubplotsFalseTrue/FalseAuto-adjust spacing to prevent overlap
cmapHeatmap/scatter"viridis""viridis", "coolwarm", "RdBu_r", etc.Colormap for data mapping
alphaAll plot types1.00.0-1.0Transparency (0=invisible, 1=opaque)
linewidthLine plots1.50.5-5.0Line thickness in points
sScatter201-500Marker size in points²
binsHistogram105-100 or arrayNumber of histogram bins
projectionadd_subplotNone"3d", "polar"Axes projection type

Best Practices

  1. Always use the OO interface (fig, ax = plt.subplots()) for production code. Reserve plt.plot() for quick interactive exploration only

  2. Use constrained_layout=True to prevent overlapping labels and titles:

    python
    fig, ax = plt.subplots(figsize=(8, 5), constrained_layout=True)
  3. Choose accessible colormaps: Use viridis, cividis, or plasma (perceptually uniform, colorblind-safe). Avoid jet and rainbow

  4. Close figures after saving to prevent memory leaks in loops:

    python
    plt.close(fig)  # After savefig
  5. Set DPI appropriately: 300 for print/journal, 150 for web/slides, 72 for screen-only

  6. Use rasterized=True for large datasets to reduce PDF/SVG file size:

    python
    ax.scatter(x, y, rasterized=True)  # Vector labels + rasterized data
  7. Label panels consistently: Use bold letters (A, B, C, D) at top-left of each subplot for multi-panel figures

Common Recipes

Recipe: Custom Color Palette

When to use: Consistent colors across multiple figures in a paper.

python
import matplotlib.pyplot as plt

# Define a custom palette
palette = {"control": "#4C72B0", "treatment": "#DD8452", "combo": "#55A868"}

fig, ax = plt.subplots()
for group, color in palette.items():
    ax.bar(group, [5, 7, 6][list(palette.keys()).index(group)], color=color)
plt.savefig("custom_palette.png", dpi=300, bbox_inches="tight")

Recipe: Twin Y-Axes

When to use: Plotting two variables with different scales on the same figure.

python
import matplotlib.pyplot as plt
import numpy as np

fig, ax1 = plt.subplots(figsize=(8, 5))
x = np.arange(10)
ax1.bar(x, np.random.randint(10, 100, 10), alpha=0.7, color="steelblue", label="Count")
ax1.set_ylabel("Count", color="steelblue")

ax2 = ax1.twinx()
ax2.plot(x, np.cumsum(np.random.rand(10)), "r-o", linewidth=2, label="Cumulative")
ax2.set_ylabel("Cumulative", color="red")

fig.legend(loc="upper left", bbox_to_anchor=(0.15, 0.95))
plt.savefig("twin_axes.png", dpi=300, bbox_inches="tight")

Recipe: Inset Zoom Plot

When to use: Showing a zoomed-in region of a larger plot.

python
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(8, 5))
x = np.linspace(0, 10, 500)
y = np.sin(x) * np.exp(-x / 5)
ax.plot(x, y, "b-", linewidth=2)

# Inset
axins = ax.inset_axes([0.5, 0.5, 0.4, 0.4])
axins.plot(x, y, "b-", linewidth=2)
axins.set_xlim(1, 3); axins.set_ylim(0.2, 0.8)
ax.indicate_inset_zoom(axins, edgecolor="black")
plt.savefig("inset_zoom.png", dpi=300, bbox_inches="tight")

Troubleshooting

ProblemCauseSolution
Overlapping labels/titlesNo layout managementAdd constrained_layout=True to plt.subplots()
UserWarning: tight_layoutIncompatible with constrained_layoutUse only one: constrained_layout OR tight_layout(), not both
Blurry figures in JupyterLow default DPISet %config InlineBackend.figure_format = 'retina'
Memory grows in loopsFigures not closedAdd plt.close(fig) after each savefig()
Font not found warningMissing system fontUse plt.rcParams["font.sans-serif"] = ["DejaVu Sans"]
Large PDF/SVG file sizeMany data points in vectorUse rasterized=True on heavy artists
3D plot rotation stuckInteractive backend issueUse %matplotlib widget in Jupyter or plt.show() in scripts
Colorbar wrong sizeDefault sizing doesn't match axesUse fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)

References

Frequently asked questions

What does the Matplotlib Scientific Plotting AI skill do?

Low-level Python plotting for scientific figures: publication-quality line, scatter, bar, heatmap, contour, 3D; multi-panel layouts; fine control of every element. PNG/PDF/SVG export. Use seaborn for quick stats, plotly for interactive.

Why use Matplotlib Scientific Plotting on TypingMind?

Because you install it once and use it with any model. Matplotlib Scientific Plotting is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Matplotlib Scientific Plotting in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/data-visualization/matplotlib-scientific-plotting. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Matplotlib Scientific Plotting?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Matplotlib Scientific Plotting?

As many as you like. As long as a model supports skills, you can use Matplotlib Scientific Plotting with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Matplotlib Scientific Plotting AI skill free?

Yes. It is published on GitHub by jaechang-hits under the PSF-based license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇