| name | data_visualization |
| description | Use this skill whenever the task involves making a figure. Produces publication-quality matplotlib charts (bar, scatter, line) with a colorblind-safe palette, saves them, and self-checks the result with `figure_check`. |
Data Visualization
Every figure should be clear, colorblind-safe, and self-contained (readable without the surrounding text). This skill gives you a small toolkit to reach that bar without writing matplotlib boilerplate from scratch.
The recommended workflow is:
- Apply the publication theme once per session.
- Pick a recipe (bar / scatter / line) and adapt it.
- Save as PNG (and SVG if you want a vector copy).
- Run
figure_check to get a vision-model review — fix any issues before showing the user.
1. Global theme — apply FIRST in every session
import matplotlib
import matplotlib.pyplot as plt
def set_publication_theme(base_font_size: int = 8, line_width: float = 0.75):
"""Apply a clean, publication-quality matplotlib theme."""
matplotlib.rcParams.update({
"font.family": "sans-serif",
"font.sans-serif": ["Arial", "Helvetica", "DejaVu Sans"],
"font.size": base_font_size,
"axes.titlesize": base_font_size + 1,
"axes.labelsize": base_font_size,
"xtick.labelsize": base_font_size - 1,
"ytick.labelsize": base_font_size - 1,
"legend.fontsize": base_font_size - 1,
"axes.linewidth": line_width,
"axes.spines.top": False,
"axes.spines.right": False,
"axes.grid": False,
"xtick.major.width": line_width,
"ytick.major.width": line_width,
"xtick.direction": "out",
"ytick.direction": "out",
"figure.dpi": 150,
"savefig.dpi": 300,
"savefig.bbox": "tight",
"pdf.fonttype": 42,
"svg.fonttype": "none",
"legend.frameon": False,
})
set_publication_theme()
Key rules baked into the theme:
- No top / right spines.
- No legend frame.
- Editable text when exported to PDF or SVG.
2. Colorblind-safe palette (Wong, 2011)
PALETTE = [
"#0072B2",
"#E69F00",
"#009E73",
"#CC79A7",
"#56B4E9",
"#D55E00",
"#F0E442",
"#000000",
]
Never use matplotlib's default colour cycle or jet. For >8 categories, encode shape + colour together.
3. Recipes
Bar chart (comparing values across a few items)
fig, ax = plt.subplots(figsize=(4.5, 3))
ax.bar(labels, values, color=PALETTE[:len(values)], width=0.6, linewidth=0)
ax.set_ylabel("Molecular weight (g/mol)")
ax.set_title("Comparison of drug MWs")
ax.tick_params(axis="x", rotation=20)
fig.tight_layout()
fig.savefig("mw_comparison.png", dpi=300)
plt.close(fig)
Scatter (two numeric variables)
fig, ax = plt.subplots(figsize=(4, 3))
ax.scatter(x, y, s=20, alpha=0.75, color=PALETTE[0], linewidths=0)
ax.set_xlabel("LogP")
ax.set_ylabel("Molecular weight (g/mol)")
fig.tight_layout()
fig.savefig("scatter.png", dpi=300)
plt.close(fig)
Line (trend / dose-response)
fig, ax = plt.subplots(figsize=(4.5, 3))
for i, (label, y) in enumerate(series.items()):
ax.plot(x, y, color=PALETTE[i], marker="o", markersize=4, linewidth=1.2, label=label)
ax.set_xlabel("Dose (mg)")
ax.set_ylabel("Response (%)")
ax.legend(title="Compound")
fig.tight_layout()
fig.savefig("dose_response.png", dpi=300)
plt.close(fig)
4. Saving — always close the figure
fig.savefig("plot.png", dpi=300)
fig.savefig("plot.svg")
plt.close(fig)
After saving, tell the user the file path — that is the deliverable.
5. Self-check (MANDATORY)
Always review the saved figure with figure_check and fix any issues it flags:
from utils.codeact_skills.skills.data_visualization.scripts.figure_check import figure_check
feedback = figure_check("mw_comparison.png")
for dimension, comment in feedback.items():
print(f"{dimension}: {comment}")
figure_check returns a dict with five short comments:
Readability, Panel Arrangement, Axis Labels, Legend, Color.
If anything looks wrong, regenerate the figure with the fix applied before reporting back to the user.
6. Common mistakes to avoid
| ❌ | ✅ |
|---|
| Default matplotlib colors | Wong 2011 palette |
frameon=True on legend | frameon=False (already in the theme) |
| Top/right spines visible | Removed by the theme |
fontsize=12 for small panels | 7–8 pt body, 9 pt panel labels |
| Axis label without units | "Molecular weight (g/mol)" |
Forgetting plt.close(fig) | Always close after saving |
Skipping figure_check | Always run it before reporting |