Enhanced matplotlib styling, color management, and utility library for publication-quality figures
Project description
dartwork-mpl
Publication-quality matplotlib — a thin utility layer, not a wrapper.
dartwork-mpl keeps Figure / Axes 100% native and adds the parts matplotlib
makes tedious: a physical-width geometry API, curated style presets, an OKLCH-aware
color system, deterministic content-aware layout, visual validation, and a
first-class integration for AI coding assistants (an MCP server + a bundled prompt
corpus). You never learn a new plotting API — you keep writing matplotlib, just
without the friction.
import matplotlib.pyplot as plt
import dartwork_mpl as dm
dm.style.use("scientific") # 1. curated preset
fig, ax = plt.subplots(figsize=dm.figsize("13cm", "standard")) # 2. physical width × aspect
ax.plot(x, y, color="oc.blue5", lw=dm.lw(0))
ax.set_xlabel("Time [s]")
dm.simple_layout(fig) # 3. content-aware margins
dm.save_formats(fig, "figure", formats=("svg", "png", "pdf")) # 4. multi-format save
That four-step pattern — preset → figsize(width, aspect) → simple_layout →
save_formats — is the whole workflow. No tight_layout(), no hand-tuned
figsize=(w, h) arithmetic, no dpi= guesswork.
Installation
pip install dartwork-mpl # or: uv add dartwork-mpl
Requires Python 3.10+. The core install is intentionally lean; add an extra only when you need it:
| Extra | Enables | Pulls in |
|---|---|---|
[notebook] |
dm.show() inline SVG display in Jupyter |
ipython |
[mcp] |
the MCP server for AI assistants | fastmcp, httpx |
[ui] |
the interactive parameter viewer | fastapi, uvicorn |
pip install "dartwork-mpl[notebook]" # or [mcp], [ui]
Highlights
- Geometry, decoupled from inches.
dm.figsize("13cm", "standard")takes a physical width (cm / in / mm / pt, ordm.col1= 9 cm /dm.col2= 17 cm) and one of six aspect tokens (square / portrait / standard / golden / wide / cinema); the height follows. Bare numbers are rejected so the unit is always explicit. - Deterministic layout.
simple_layout(fig)measures every visible artist and places the GridSpec arithmetically — reproducible across machines, unliketight_layout()'s heuristics.margin="2%"(ordm.mm(2)) adds a buffer. - OKLCH-aware color. Named palettes (
oc.*Open Color,tw.*Tailwind,md.*,ad.*,cu.*,pr.*) plus aColorclass spanning OKLab / OKLCH / RGB / hex with perceptual interpolation (cspace) and gamut-correct mapping. - Curated styling. Seven presets (
scientific,report,presentation, …), each with a Korean-krvariant, and preset-relative scaling helpersfs/fw/lwso literals never drift when you switch themes. - Validation & export.
validate_figure(fig)flags overflow, text/legend overlap, tick crowding, and empty axes — invisible failures in headless agent pipelines.save_formats(fig, ...)writes SVG / PNG / PDF / EPS at once. - AI-native. A bundled MCP server exposes lint + auto-fix, figure validation, color lookup, and the live policy corpus to Claude Code / Cursor / Windsurf. No-MCP agents read the same corpus from disk.
- Batteries included. Material Design Icons + Font Awesome 6 fonts, ready-made
plot templates (
plot_diverging_bar, …), and a FastAPI viewer for live tuning.
Core API at a glance
import dartwork_mpl as dm
# ── Geometry ──────────────────────────────────────────────────────────
dm.figsize("13cm", "wide") # width × aspect token → inch tuple
dm.figsize("13cm", 0.6) # ...or a numeric ratio / "8cm" / dm.cm(8)
dm.cm(13); dm.mm(170); dm.inch(4.6); dm.pt(24) # Length values
dm.col1; dm.col2 # 9 cm / 17 cm academic-column sugar
# ── Styling & scaling ─────────────────────────────────────────────────
dm.style.use("scientific") # apply a preset
dm.style.stack(["base", "font-scientific", "lang-kr"]) # compose
dm.fs(2); dm.fw(1); dm.lw(-0.3) # preset-relative font size / weight / line width
# ── Color ─────────────────────────────────────────────────────────────
ax.plot(x, y, color="oc.blue5") # named palettes register with matplotlib
dm.color("oc.blue5") # parse name / "#4285F4" / "rgb(...)" / "oklch(...)"
dm.oklch(0.7, 0.15, 150); dm.rgb(66, 133, 244); dm.hex("#4285F4")
dm.cspace("#FF0000", "#0000FF", n=5, space="oklch") # perceptual interpolation
dm.mix_colors("oc.blue5", "white", alpha=0.35)
# ── Layout & annotation ───────────────────────────────────────────────
dm.simple_layout(fig) # deterministic content-aware margins
dm.simple_layout(fig, margin="2%", gs=gs) # buffer + target a GridSpec
dm.label_axes(axes) # (a) (b) (c) panel labels
dm.arrow_axis(ax, "x", "Cost") # Low ◄── Cost ──► High
# ── Validate, export, icons ───────────────────────────────────────────
dm.validate_figure(fig) # overflow / overlap / tick-crowding / empty
dm.save_formats(fig, "fig", formats=("png", "svg", "pdf"), dpi=300)
mdi = dm.icon_font("mdi") # also "fa-solid" / "fa-regular" / "fa-brands"
# ── Plot templates ────────────────────────────────────────────────────
from dartwork_mpl.templates import plot_diverging_bar
fig, ax = plot_diverging_bar(labels=["A", "B"], neg_values=[-30, -15], pos_values=[40, 55])
See the usage guide and API reference for the full surface.
Style presets
| Preset | Use case |
|---|---|
scientific |
Compact fonts for academic papers and journals |
report |
Reports and dashboards, cleaner spines |
minimal |
Tufte-style, data-ink focus — no spines or ticks |
presentation |
Large fonts for projected slides |
poster |
Extra-large fonts and thick lines for posters |
web |
On-screen readability for docs and notebooks |
dark |
Dark backgrounds for Jupyter and dark-mode slides |
Each has a Korean -kr variant (scientific-kr, report-kr, …) with Korean-aware
fonts. List them with dm.list_styles().
AI-assisted development (MCP)
dartwork-mpl ships a built-in Model Context Protocol server so AI coding assistants pull the current policy guides, color palettes, lint catalog, and helper tools straight into the chat — no copy-pasting docs. It exposes 13 tools (lint + auto-fix, figure validation, render, color lookup, info), 12 resources + 3 resource templates (the prompt corpus + 18 plot templates), and 2 prompts.
pip install "dartwork-mpl[mcp]" # installs fastmcp + httpx; adds the dartwork-mpl-mcp script
Point your client at the dartwork-mpl-mcp console script — e.g. Claude Code
(~/.claude.json) or Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"dartwork-mpl": { "command": "dartwork-mpl-mcp" }
}
}
Restart the client and ask it to list its MCP resources to confirm. Windsurf,
Antigravity, generic stdio setups, the full tool/resource catalog, and the
local-clone variant are covered in
docs/integrations/mcp_server.md.
No MCP? The same corpus is bundled in the wheel and reachable from Python —
dm.get_agent_doc("llms-full")(also"AGENTS","CLAUDE","llms") returns the text,dm.agent_doc_path(name)its path. The repo-rootCLAUDE.md/AGENTS.md/llms.txt(per the llmstxt.org spec) are the 30-second onboarding.
Documentation
- Quickstart — install, first figure, save
- Usage guide — width/aspect, layout, color, patterns
- Color system — palettes, OKLCH, colormaps
- Example gallery — rendered, copy-pasteable
- API reference — every public function and class
- Design philosophy — why thin utilities, not a wrapper
Migrating from earlier versions
The 0.3 names (dm.SW / MW / TW / DW, dm.FS_*, dm.WIDTHS, dm.cm2in,
dm.agent_utils, dm.xplot), the 0.4-era figure constructors (dm.subplots,
dm.figure), and the 0.5 prompt-corpus installer (dm.install_llm_txt and
friends) have all been removed. Every old access path raises AttributeError
/ ModuleNotFoundError naming its replacement — the canonical pattern is
plt.subplots(figsize=dm.figsize("13cm", "standard")) with a separate
dm.style.use(...). Full mapping: docs/migration.md ·
CHANGELOG.
Project layout
src/dartwork_mpl/
├── units.py / scale.py # figsize, cm/mm/inch/pt, col1/col2 · fs/fw/lw
├── style.py # Style class + preset management
├── colors/ # Color (OKLab/OKLCH/RGB/hex) + named palettes
├── layout.py / annotation.py # simple_layout, label_axes, arrow_axis
├── validate.py / lint.py # validate_figure · lint + migrate_legacy_code
├── io.py / formatting.py # save_formats, show · format_axis_*
├── icon.py / font.py / cmap.py / diagnostics/ # fonts, colormaps, viz helpers
├── templates/ / helpers/ # plot templates · high-level composition helpers
├── agent.py / prompt.py # bundled LLM corpus · prompt guides
├── mcp/ # MCP server (server / resources / tools / prompts)
├── ui/ # interactive FastAPI viewer
└── asset/ # bundled styles, colors, fonts, icons, prompts
Contributing & issues
Bug reports and feature requests go to the GitHub issue tracker. Released under the MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dartwork_mpl-0.5.0.tar.gz.
File metadata
- Download URL: dartwork_mpl-0.5.0.tar.gz
- Upload date:
- Size: 28.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34df19b327acf3380a23edfc1f4948459afb22c83a4c4c6e22ffaa9f3ad9d5ed
|
|
| MD5 |
f817ad9e5b832850643a68a6a0676a21
|
|
| BLAKE2b-256 |
31f6cc4f031fd52695931a0c0cbfbbc323a8f1574d22767d40b56fecc883b0d3
|
Provenance
The following attestation bundles were made for dartwork_mpl-0.5.0.tar.gz:
Publisher:
release.yml on dartworklabs/dartwork-mpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dartwork_mpl-0.5.0.tar.gz -
Subject digest:
34df19b327acf3380a23edfc1f4948459afb22c83a4c4c6e22ffaa9f3ad9d5ed - Sigstore transparency entry: 1748647712
- Sigstore integration time:
-
Permalink:
dartworklabs/dartwork-mpl@759fd48394aa0f6ab06398cdf38043b769889bce -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/dartworklabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@759fd48394aa0f6ab06398cdf38043b769889bce -
Trigger Event:
push
-
Statement type:
File details
Details for the file dartwork_mpl-0.5.0-py3-none-any.whl.
File metadata
- Download URL: dartwork_mpl-0.5.0-py3-none-any.whl
- Upload date:
- Size: 28.9 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55897a930bff5a370f078ac59b37da4721ef14fc8a5dd13f0f10fd88c35c93e8
|
|
| MD5 |
b4e02798a3623b01aa34ff3f7b251232
|
|
| BLAKE2b-256 |
2442d53c1f6186effeef399debcd063a824888a3427e482ce6b26c88e4c7a89d
|
Provenance
The following attestation bundles were made for dartwork_mpl-0.5.0-py3-none-any.whl:
Publisher:
release.yml on dartworklabs/dartwork-mpl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dartwork_mpl-0.5.0-py3-none-any.whl -
Subject digest:
55897a930bff5a370f078ac59b37da4721ef14fc8a5dd13f0f10fd88c35c93e8 - Sigstore transparency entry: 1748647860
- Sigstore integration time:
-
Permalink:
dartworklabs/dartwork-mpl@759fd48394aa0f6ab06398cdf38043b769889bce -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/dartworklabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@759fd48394aa0f6ab06398cdf38043b769889bce -
Trigger Event:
push
-
Statement type: